WinHttpSendRequest 函数 (winhttp.h)

WinHttpSendRequest 函数将指定的请求发送到 HTTP 服务器。

语法

WINHTTPAPI BOOL WinHttpSendRequest(
  [in]           HINTERNET hRequest,
  [in, optional] LPCWSTR   lpszHeaders,
  [in]           DWORD     dwHeadersLength,
  [in, optional] LPVOID    lpOptional,
  [in]           DWORD     dwOptionalLength,
  [in]           DWORD     dwTotalLength,
  [in]           DWORD_PTR dwContext
);

参数

[in] hRequest

WinHttpOpenRequest 返回的 HINTERNET 句柄。

[in, optional] lpszHeaders

指向字符串的指针,该字符串包含要追加到请求的其他标头。 如果没有要追加的其他标头,则可以 WINHTTP_NO_ADDITIONAL_HEADERS 此参数。

[in] dwHeadersLength

一个无符号长整数值,该值包含附加标头的长度(以字符为单位)。 如果此参数为 -1LpwszHeaders 不为 NULL,则此函数假定 pwszHeadersnull 结尾,并计算长度。

[in, optional] lpOptional

指向缓冲区的指针,该缓冲区包含要紧接在请求标头之后发送的任何可选数据。 此参数通常用于 POST 和 PUT 操作。 可选数据可以是发布到服务器的资源或数据。 如果没有要发送的可选数据,则可以 WINHTTP_NO_REQUEST_DATA 此参数。

如果 dwOptionalLength 参数为 0,则忽略此参数并将其设置为 NULL

在关闭请求句柄或完成 对 WinHttpReceiveResponse 的 调用之前,此缓冲区必须保持可用。

[in] dwOptionalLength

一个无符号长整数值,该值包含可选数据的长度(以字节为单位)。 如果没有要发送的可选数据,此参数可以为零。

lpOptional 参数不为 NULL 时,此参数必须包含有效的长度。 否则, 将忽略 lpOptional 并将其设置为 NULL

[in] dwTotalLength

一个无符号长整型值,该值包含发送的总数据的长度(以字节为单位)。 此参数指定请求的 Content-Length 标头。 如果此参数的值大于 dwOptionalLength 指定的长度,则可以使用 WinHttpWriteData 发送其他数据。

dwTotalLength 不得在调用同一请求的 WinHttpSendRequest 之间更改。 如果需要更改 dwTotalLength ,调用方应创建一个新请求。

[in] dwContext

指向指针大小的变量的指针,该变量包含应用程序定义的值,该值随请求句柄一起传递给任何回调函数。

返回值

如果成功,则返回 TRUE ,否则返回 FALSE 。 有关扩展的错误信息,请调用 GetLastError。 下表列出了错误代码。

错误代码 说明
ERROR_WINHTTP_CANNOT_CONNECT
如果与服务器的连接失败,则返回 。
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED
安全 HTTP 服务器需要客户端证书。 应用程序通过使用 WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST 选项调用 WinHttpQueryOption 来检索证书颁发者列表。

如果服务器请求客户端证书,但不需要该证书,则应用程序可以使用 WINHTTP_OPTION_CLIENT_CERT_CONTEXT 选项交替调用 WinHttpSetOption。 在这种情况下,应用程序在 WinHttpSetOptionlpBuffer 参数中指定WINHTTP_NO_CLIENT_CERT_CONTEXT宏。 有关详细信息,请参阅 WINHTTP_OPTION_CLIENT_CERT_CONTEXT 选项。带 SP1 的 Windows Server 2003、SP2 和 Windows 2000 的 Windows XP: 不支持此错误。

ERROR_WINHTTP_CONNECTION_ERROR
与服务器的连接已重置或终止,或者遇到不兼容的 SSL 协议。 例如,WinHTTP 版本 5.1 不支持 SSL2,除非客户端专门启用 SSL2。
ERROR_WINHTTP_INCORRECT_HANDLE_STATE
无法执行请求的操作,因为提供的句柄未处于正确的状态。
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
此操作提供的句柄类型不正确。
ERROR_WINHTTP_INTERNAL_ERROR
发生了内部错误。
ERROR_WINHTTP_INVALID_URL
URL 无效。
ERROR_WINHTTP_LOGIN_FAILURE
登录尝试失败。 遇到此错误时,应使用 WinHttpCloseHandle 关闭请求句柄。 在重试最初生成此错误的函数之前,必须创建新的请求句柄。
ERROR_WINHTTP_NAME_NOT_RESOLVED
无法解析服务器名称。
ERROR_WINHTTP_OPERATION_CANCELLED
操作被取消,通常是因为操作之前关闭了操作请求的句柄。
ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW
当传入响应超过内部 WinHTTP 大小限制时返回。
ERROR_WINHTTP_SECURE_FAILURE
在服务器发送的安全套接字层 (SSL) 证书中发现一个或多个错误。 若要确定遇到的错误类型,请在状态回调函数中通过 WINHTTP_CALLBACK_STATUS_SECURE_FAILURE 通知进行验证。 有关详细信息,请参阅 WINHTTP_STATUS_CALLBACK
ERROR_WINHTTP_SHUTDOWN
WinHTTP 函数支持已关闭或卸载。
ERROR_WINHTTP_TIMEOUT
请求超时。
ERROR_WINHTTP_UNRECOGNIZED_SCHEME
URL 指定了“http:”或“https:”以外的方案。
ERROR_NOT_ENOUGH_MEMORY
内存不足,无法完成请求的操作。 (Windows 错误代码)

Windows Server 2003、Windows XP 和 Windows 2000: 使用 WINHTTP_OPTION_PORT_RESERVATION 选项设置的 TCP 预留范围不够大,无法发送此请求。

ERROR_INVALID_PARAMETER
dwTotalLength 参数中指定的内容长度与 Content-Length 标头中指定的长度不匹配。

当存在 Transfer-Encoding 标头时,lpOptional 参数必须为 NULL,dwOptionalLength 参数必须为零。

当存在 Transfer-Encoding 标头时,不能显示 Content-Length 标头。

ERROR_WINHTTP_RESEND_REQUEST
由于重定向或身份验证质询,应用程序必须调用 WinHttpSendRequest

带 SP1 的 Windows Server 2003、SP2 和 Windows 2000 的 Windows XP: 不支持此错误。

注解

即使在异步模式下使用 WinHTTP,即在 WinHttpOpen 中设置了WINHTTP_FLAG_ASYNC时,此函数也可以同步或异步运行。 在任一情况下,如果请求成功发送,则会回调应用程序,完成状态设置为 WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETEWINHTTP_CALLBACK_STATUS_REQUEST_ERROR完成指示操作异步完成,但失败。 收到 WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE 状态回调后,应用程序可以使用 WinHttpReceiveResponse 开始接收来自服务器的响应。 在此之前,不能调用其他异步函数,否则返回 ERROR_WINHTTP_INCORRECT_HANDLE_STATE

在关闭请求句柄或完成对 WinHttpReceiveResponse 的调用之前,应用程序不得删除或更改 lpOptional 指向的缓冲区,因为在接收响应的过程中可能会遇到需要可选数据的身份验证质询或重定向。 如果必须使用 WinHttpCloseHandle 中止操作,则应用程序必须使缓冲区保持有效,直到收到带有ERROR_WINHTTP_OPERATION_CANCELLED错误代码的回调WINHTTP_CALLBACK_STATUS_REQUEST_ERROR为止。

如果同步使用 WinHTTP,即在 WinHttpOpen 中未设置WINHTP_FLAG_ASYNC时,即使注册了回调函数,也不会以完成状态调用应用程序。 在此模式下,当 WinHttpSendRequest 返回时,应用程序可以调用 WinHttpReceiveResponse

WinHttpSendRequest 函数将指定的请求发送到 HTTP 服务器,并允许客户端指定要随请求一起发送的其他标头。

此函数还允许客户端指定要在请求标头之后立即发送到 HTTP 服务器的可选数据。 此功能通常用于 PUT 和 POST 等写入操作。

应用程序可以在对 WinHttpSendRequest 的多个调用中使用相同的 HTTP 请求句柄来重新发送同一请求,但应用程序必须读取上一次调用返回的所有数据,然后才能再次调用此函数。

将验证随此函数添加的请求标头的名称和值。 标头必须格式良好。 有关有效 HTTP 标头的详细信息,请参阅 RFC 2616。 如果使用无效标头,此函数将失败, GetLastError 将返回 ERROR_INVALID_PARAMETER。 未添加无效标头。

Windows 2000: 从多个线程发送请求时,网络和 CPU 性能可能会显著下降。

Windows XP 和 Windows 2000: 请参阅 运行时要求

WinHttpSetStatusCallback

如果状态回调函数已随 WinHttpSetStatusCallback 一起安装,则在 WinHttpSetStatusCallbackdwNotificationFlags 参数中设置的以下通知指示发送请求的进度:
  • ) 未实现WINHTTP_CALLBACK_STATUS_DETECTING_PROXY (
  • 仅在异步模式下) WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE (
  • WINHTTP_CALLBACK_STATUS_REDIRECT
  • WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
  • WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
注意 在 Windows 7 和 Windows Server 2008 R2 上,以下所有通知均已弃用。
 
  • WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
  • WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
  • WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
  • WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
  • WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
  • WINHTTP_CALLBACK_STATUS_REQUEST_SENT
  • WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
  • WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
如果服务器关闭连接,则还会发送以下通知,前提是已在 WinHttpSetStatusCallbackdwNotificationFlags 参数中设置这些通知:
  • WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
  • WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED

支持大于 4 GB 的上传

从 Windows Vista 和 Windows Server 2008 开始,WinHttp 支持使用 Content-Length 标头) 上传最大为 LARGE_INTEGER (2^64 字节的文件。 调用 WinHttpSendRequest 中指定的有效负载长度限制为 DWORD (2^32 字节) 。 若要将数据上传到大于 DWORD 的 URL,应用程序必须在请求的 Content-Length 标头中提供长度。 在这种情况下,WinHttp 客户端应用程序调用 WinHttpSendRequest ,并将 dwTotalLength 参数设置为 WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH

如果 Content-Length 标头指定的长度小于 2^32,则应用程序还必须在对 WinHttpSendRequest 的调用中指定内容长度。 如果 dwTotalLength 参数与 Content-Length 标头中指定的长度不匹配,则调用将失败并返回 ERROR_INVALID_PARAMETER

可以在调用 WinHttpAddRequestHeaders 中添加 Content-Length 标头,也可以在 WinHttpSendRequestlpszHeader 参数中指定,如以下代码示例所示。

BOOL fRet = WinHttpSendRequest(
			hReq,
			L"Content-Length: 68719476735\r\n",
			-1L,
			WINHTTP_NO_REQUEST_DATA,
			0,
			WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
			pMyContent);

传输编码标头

从 Windows Vista 和 Windows Server 2008 开始,WinHttp 使应用程序能够对发送到服务器的数据执行分块传输编码。 当 WinHttp 请求上存在 Transfer-Encoding 标头时,调用 WinHttpSendRequest 中的 dwTotalLength 参数设置为 WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH应用程序会在一次或多次调用 WinHttpWriteData 时发送实体正文。 WinHttpSendRequestlpOptional 参数必须为 NULL,dwOptionLength 参数必须为零,否则返回ERROR_WINHTTP_INVALID_PARAMETER错误。 为了终止分块数据传输,应用程序会生成一个零长度区块,并在最后一次调用 WinHttpWriteData 时将其发送。

示例

下面的代码示例演示如何获取 HINTERNET 句柄、打开 HTTP 会话、创建请求标头,并将该标头发送到服务器。

    BOOL  bResults = FALSE;
    HINTERNET hSession = NULL,
              hConnect = NULL,
              hRequest = NULL;

    // Use WinHttpOpen to obtain a session handle.
    hSession = WinHttpOpen(  L"A WinHTTP Example Program/1.0", 
                             WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                             WINHTTP_NO_PROXY_NAME, 
                             WINHTTP_NO_PROXY_BYPASS, 0);

    // Specify an HTTP server.
    if (hSession)
        hConnect = WinHttpConnect( hSession, L"www.wingtiptoys.com",
                                   INTERNET_DEFAULT_HTTP_PORT, 0);

    // Create an HTTP Request handle.
    if (hConnect)
        hRequest = WinHttpOpenRequest( hConnect, L"PUT", 
                                       L"/writetst.txt", 
                                       NULL, WINHTTP_NO_REFERER, 
                                       WINHTTP_DEFAULT_ACCEPT_TYPES, 
                                       0);

    // Send a Request.
    if (hRequest) 
        bResults = WinHttpSendRequest( hRequest, 
                                       WINHTTP_NO_ADDITIONAL_HEADERS,
                                       0, WINHTTP_NO_REQUEST_DATA, 0, 
                                       0, 0);

    // Place additional code here.


    // Report errors.
    if (!bResults)
        printf("Error %d has occurred.\n",GetLastError());

    // Close open handles.
    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);

要求

要求
最低受支持的客户端 Windows XP、Windows 2000 Professional SP3 [仅限桌面应用]
最低受支持的服务器 Windows Server 2003、Windows 2000 Server SP3 [仅限桌面应用]
目标平台 Windows
标头 winhttp.h
Library Winhttp.lib
DLL Winhttp.dll
可再发行组件 Windows XP 和 Windows 2000 上的 WinHTTP 5.0 和 Internet Explorer 5.01 或更高版本。

另请参阅

关于 Microsoft Windows HTTP Services (WinHTTP)

WINHTTP_STATUS_CALLBACK

WinHTTP 版本

WinHttpCloseHandle

WinHttpConnect

WinHttpOpen

WinHttpOpenRequest

WinHttpReceiveResponse