WinInet和winHttp库使用简介

2023-10-10 02:30
文章标签 使用 简介 wininet winhttp

本文主要是介绍WinInet和winHttp库使用简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

初始化

InternetOpen

HINTERNET InternetOpen(LPCSTR lpszAgent,DWORD  dwAccessType,LPCSTR lpszProxyName,LPCSTR lpszProxyBypass,DWORD  dwFlags
);

"InternetOpen"是Windows操作系统提供的函数之一,位于WinINet库中。它用于初始化WinINet网络会话,并返回一个用于后续网络操作的句柄。

参数说明:

  • lpszAgent: 一个指向字符串的指针,表示应用程序名称或标识符,用于标识创建的会话。
  • dwAccessType: 指定访问类型,可以是以下几个值之一:
    • INTERNET_OPEN_TYPE_PRECONFIG`: 使用系统配置的代理设置。
    • INTERNET_OPEN_TYPE_DIRECT: 直接连接到互联网。
    • INTERNET_OPEN_TYPE_PROXY: 使用指定的代理设置。
    • INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY: 使用系统配置的代理设置,但不自动检测自动代理设置。
  • lpszProxyName: 一个指向字符串的指针,表示使用的代理服务器名称。
  • lpszProxyBypass: 一个指向字符串的指针,表示不使用代理的地址。
  • dwFlags:一些选项标志,可以是0或以下值的组合:
    • INTERNET_FLAG_ASYNC: 异步模式,表示启用异步操作。在异步模式下,函数将立即返回而不阻塞当前线程,并通过回调函数来处理请求的结果和状态。
    • INTERNET_FLAG_FROM_CACHE: 如果可用,从缓存中获取数据。
    • INTERNET_FLAG_OFFLINE: 无网络连接时,从缓存中获取数据。

返回值:

  • 成功时,返回一个有效的HINTERNET句柄,用于后续的网络操作。
  • 失败时,返回NULL,可以通过调用GetLastError()获取错误代码。

使用InternetOpen函数是进行网络操作的第一步,它初始化了一个网络会话,然后可以通过后续的WinINet函数来进行HTTP请求、FTP传输、下载文件等网络操作。

InternetSetStatusCallback

InternetSetStatusCallback是Windows操作系统提供的函数之一,位于WinINet库中。它用于为异步的WinINet操作设置回调函数,以便在操作状态发生变化时接收通知。

INTERNET_STATUS_CALLBACK InternetSetStatusCallback(HINTERNET                 hInternet,INTERNET_STATUS_CALLBACK lpfnInternetCallback
);

参数说明:

  • hInternet: 要设置回调函数的网络会话或请求句柄。

  • lpfnInternetCallback: 回调函数指针,指向用于接收回调通知的函数。回调函数必须符合INTERNET_STATUS_CALLBACK类型的定义。

    • 回调函数的定义如下:
    void CALLBACK InternetStatusCallback(HINTERNET hInternet,DWORD_PTR dwContext,DWORD     dwInternetStatus,LPVOID    lpvStatusInformation,DWORD     dwStatusInformationLength
    );

    参数说明:

    • hInternet: 引发状态回调的网络会话或请求句柄。

    • dwContext: 在调用InternetSetStatusCallback时传递的上下文参数。

    • dwInternetStatus: 表示引发回调的状态类型,具体取决于WinINet操作的不同阶段和情况。

    • lpvStatusInformation: 指向一个包含有关状态的信息的缓冲区。

    • dwStatusInformationLength: 缓冲区的大小。

    • 回调函数的主要作用是接收WinINet异步操作的状态变化通知,例如请求的进度、连接状态、错误信息等。在设置了回调函数后,当相应的操作状态发生变化时,系统会自动调用回调函数并传递相关的状态信息。

    通过设置回调函数,可以在异步操作中实现非阻塞的网络请求,提高程序的并发性和响应性。回调函数中可以根据不同的状态类型,采取相应的操作,比如处理请求结果、更新进度、处理错误等。

    需要注意的是,使用异步操作时,需要仔细处理回调函数的调用时机和回调数据的有效性,以确保程序的正确性和稳定性。

CRITICAL_SECTION

CRITICAL_SECTION 是 Windows API 中用于创建临界区(Critical Section)的数据结构。临界区是一种用于线程同步的机制,它可以确保在多线程环境下,只有一个线程可以进入被锁定的临界区代码段,从而实现对共享资源的互斥访问。

CRITICAL_SECTION 是一个临界区对象,使用前需要进行初始化,可以通过以下两种方式进行初始化:

  1. 使用 InitializeCriticalSection 函数进行初始化:
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
  1. 使用 InitializeCriticalSectionAndSpinCount 函数进行初始化,并指定自旋次数:
CRITICAL_SECTION cs;
InitializeCriticalSectionAndSpinCount(&cs, 4000); // 指定自旋次数,比如4000

CreateEvent

CreateEvent 是 Windows API 中用于创建一个事件对象的函数。事件对象是用于线程间通信和同步的一种内核对象,它可以用于多个线程之间的同步或线程的等待操作。

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL                  bManualReset,BOOL                  bInitialState,LPCTSTR               lpName
);

参数说明:

  • lpEventAttributes: 一个指向SECURITY_ATTRIBUTES结构的指针,用于指定事件对象的安全属性。可以为NULL,表示使用默认安全属性。
  • bManualReset: 一个BOOL值,用于指定事件是否为手动重置。如果为TRUE,则事件需要手动调用 ResetEvent 函数来重置为非信号状态;如果为FALSE,则事件会在有一个线程等待它时自动重置为非信号状态。
  • bInitialState: 一个BOOL值,用于指定事件的初始状态。如果为TRUE,则事件初始为有信号状态;如果为FALSE,则事件初始为无信号状态。
  • lpName: 一个指向以NULL结尾的字符串的指针,用于指定事件的名称。可以为NULL,表示事件没有名称。

CreateEvent 函数创建一个事件对象并返回一个句柄,可以用于后续操作。通常情况下,可以通过 SetEvent 函数将事件设置为有信号状态,通过 ResetEvent 函数将事件设置为无信号状态。线程可以调用 WaitForSingleObjectWaitForMultipleObjects 函数来等待事件对象。

需要注意的是,当不再使用事件对象时,应该通过 CloseHandle 函数关闭句柄,以释放资源:

CloseHandle(hEvent);

InternetConnect

InternetConnect 是 Windows API 中的一个函数,位于 WinINet 库中,用于在客户端应用程序中建立到远程服务器的连接。

HINTERNET InternetConnect(HINTERNET     hInternet,LPCTSTR       lpszServerName,INTERNET_PORT nServerPort,LPCTSTR       lpszUserName,LPCTSTR       lpszPassword,DWORD         dwService,DWORD         dwFlags,DWORD_PTR     dwContext
);

参数说明:

  • hInternet: 网络会话句柄,通常是通过 InternetOpen 函数返回的。
  • lpszServerName: 服务器的名称或 IP 地址,可以是一个以 NULL 结尾的字符串。
  • nServerPort: 服务器的端口号。
  • lpszUserName: 连接服务器所需的用户名,可以为 NULL。
  • lpszPassword: 连接服务器所需的密码,可以为 NULL。
  • dwService: 服务类型,通常使用 INTERNET_SERVICE_HTTPINTERNET_SERVICE_FTP 来指定 HTTP 或 FTP 服务。
  • dwFlags: 连接选项标志,可以使用 INTERNET_FLAG_PASSIVE 等来指定连接选项。
  • dwContext: 用户定义的上下文参数,将在回调函数中使用。

InternetConnect 函数用于建立与远程服务器的连接。它会返回一个连接句柄,用于后续的网络操作,如发送请求、下载数据等。

需要注意的是,在使用 WinINet API 进行网络操作时,需要先调用 InternetOpen 函数打开一个网络会话,再通过 InternetConnect 函数建立连接,最后使用其他相关函数来发送请求和接收响应。

同时,在使用完网络操作后,需要通过 InternetCloseHandle 函数关闭相关的句柄,以释放资源和确保程序的稳定性。

HttpOpenRequest

HttpOpenRequest 是 Windows API 中的一个函数,位于 WinINet 库中,用于创建一个 HTTP 请求句柄,以发送 HTTP 请求并接收服务器的响应。

HINTERNET HttpOpenRequest(HINTERNET hConnect,LPCTSTR   lpszVerb,LPCTSTR   lpszObjectName,LPCTSTR   lpszVersion,LPCTSTR   lpszReferrer,LPCTSTR   *lplpszAcceptTypes,DWORD     dwFlags,DWORD_PTR dwContext
);

参数说明:

  • hConnect: 已建立的连接句柄,通常是通过 InternetConnect 函数返回的。
  • lpszVerb: HTTP 请求的动作,例如 “GET”、“POST” 等。
  • lpszObjectName: 请求的对象,通常是请求的资源的路径。
  • lpszVersion: HTTP 协议的版本,例如 “HTTP/1.1”。
  • lpszReferrer: 引用页,通常是一个前一个页面的 URL。
  • lplpszAcceptTypes: 可接受的 MIME 类型数组。
  • dwFlags: 请求选项标志,可以使用 INTERNET_FLAG_SECURE 等来指定请求选项。
  • dwContext: 用户定义的上下文参数,将在回调函数中使用。

HttpOpenRequest 函数用于创建一个 HTTP 请求句柄,并返回该句柄用于后续的网络操作,如发送请求、接收响应等。

需要注意的是,在使用 WinINet API 进行 HTTP 请求时,需要先打开一个网络会话,然后建立连接,再创建请求句柄,最后使用其他相关函数来发送请求和接收响应。

同时,在使用完 HTTP 请求后,需要通过 InternetCloseHandle 函数关闭相关的句柄,以释放资源和确保程序的稳定性。

EnterCriticalSection

EnterCriticalSection 是 Windows API 中的一个函数,用于进入一个临界区(Critical Section)。临界区是一种同步机制,用于保护共享资源,防止多个线程同时访问和修改共享资源而导致数据不一致或竞争条件。

void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection
);

参数 lpCriticalSection 是一个指向临界区对象的指针,通常是 CRITICAL_SECTION 类型的指针。临界区对象需要先进行初始化,可以使用 InitializeCriticalSection 函数来初始化。

使用方法示例:

CRITICAL_SECTION cs; // 定义一个临界区对象
InitializeCriticalSection(&cs); // 初始化临界区对象// 在需要保护共享资源的地方,进入临界区
EnterCriticalSection(&cs);
// 访问和修改共享资源的代码
// ...
// 离开临界区
LeaveCriticalSection(&cs);

InternetCloseHandle

InternetCloseHandle 是 Windows API 中的一个函数,位于 WinINet 库中,用于关闭由 WinINet API 创建的句柄。

BOOL InternetCloseHandle(HINTERNET hInternet
);

参数 hInternet 是需要关闭的句柄。该句柄可以是通过 InternetOpenInternetConnectHttpOpenRequest 等函数创建的,用于进行网络操作。

调用 InternetCloseHandle 函数后,系统会释放相应的资源,并将句柄置为无效。

WaitForSingleObject

WaitForSingleObject 是 Windows API 中的一个函数,用于等待一个对象(如线程、进程、事件等)进入有信号状态或超时。该函数是用于多线程编程中的同步机制。

DWORD WaitForSingleObject(HANDLE hHandle,DWORD  dwMilliseconds
);

参数说明:

  • hHandle: 要等待的对象的句柄。
  • dwMilliseconds: 等待的超时时间,以毫秒为单位。如果设置为 INFINITE,表示无限等待,直到对象进入有信号状态。

WaitForSingleObject 函数将等待指定的对象进入有信号状态,即该对象完成了某个操作或事件发生。当对象进入有信号状态时,函数返回 WAIT_OBJECT_0,表示成功等待到了对象的信号。如果在指定的超时时间内对象没有进入有信号状态,则函数返回 WAIT_TIMEOUT

HttpSendRequest

HttpSendRequest 是 Windows API 中的一个函数,位于 WinINet 库中,用于向服务器发送 HTTP 请求。

BOOL HttpSendRequest(HINTERNET hRequest,LPCWSTR   lpszHeaders,DWORD     dwHeadersLength,LPVOID    lpOptional,DWORD     dwOptionalLength
);

参数说明:

  • hRequest: HTTP 请求句柄,通过调用 HttpOpenRequest 函数返回。
  • lpszHeaders: 指向包含请求头的字符串指针,可以为 NULL。
  • dwHeadersLength: 请求头字符串的长度,如果 lpszHeaders 为 NULL,则该参数应该为 0。
  • lpOptional: 指向包含请求体的缓冲区指针,可以为 NULL。
  • dwOptionalLength: 请求体缓冲区的大小,如果 lpOptional 为 NULL,则该参数应该为 0。

HttpSendRequestEx

HttpSendRequestEx 是 Windows API 中的一个函数,位于 WinINet 库中,用于向服务器发送 HTTP 请求并接收服务器的响应。它与 HttpSendRequest 类似,但提供了更多的控制和扩展选项。

BOOL HttpSendRequestEx(HINTERNET            hRequest,LPINTERNET_BUFFERS   lpBuffersIn,LPINTERNET_BUFFERS   lpBuffersOut,DWORD                dwFlags,DWORD_PTR            dwContext
);

HttpSendRequestEx 是 Windows API 中的一个函数,位于 WinINet 库中,用于向服务器发送 HTTP 请求并接收服务器的响应。它与 HttpSendRequest 类似,但提供了更多的控制和扩展选项。

函数原型如下:

cppCopy codeBOOL HttpSendRequestEx(HINTERNET            hRequest,LPINTERNET_BUFFERS   lpBuffersIn,LPINTERNET_BUFFERS   lpBuffersOut,DWORD                dwFlags,DWORD_PTR            dwContext
);

参数说明:

  • hRequest: HTTP 请求句柄,通过调用 HttpOpenRequest 函数返回。

  • lpBuffersIn: 指向一个 INTERNET_BUFFERS 结构体的指针,用于设置请求数据的缓冲区。

  • lpBuffersOut: 指向一个 INTERNET_BUFFERS 结构体的指针,用于接收服务器响应数据的缓冲区。

  • dwFlags
    

    : 指定请求的标志,可以为以下常量的组合:

    • INTERNET_FLAG_RELOAD: 强制从服务器获取资源,忽略本地缓存。
    • INTERNET_FLAG_NO_CACHE_WRITE: 不将资源添加到本地缓存。
    • INTERNET_FLAG_FORMS_SUBMIT: 将请求用于 HTML 表单的提交。
    • 其他标志,具体可参考官方文档。
  • dwContext: 用户定义的上下文参数,将在异步操作时传递给回调函数。

HttpSendRequestEx 函数用于向服务器发送 HTTP 请求,并接收服务器的响应。通过 lpBuffersInlpBuffersOut 参数,可以设置请求的数据和接收服务器的响应数据。在调用该函数后,可以使用 InternetReadFile 函数来读取服务器返回的数据。

使用方法示例:

HINTERNET hInternet = InternetOpen(...); // 打开一个 Internet 会话
HINTERNET hConnect = InternetConnect(hInternet, ...); // 建立到服务器的连接
HINTERNET hRequest = HttpOpenRequest(hConnect, ...); // 创建一个 HTTP 请求句柄INTERNET_BUFFERS buffersIn = { 0 }; // 设置请求数据的缓冲区
// 在 buffersIn 中设置请求数据的相关信息INTERNET_BUFFERS buffersOut = { 0 }; // 接收服务器响应数据的缓冲区
// 在 buffersOut 中设置接收数据的相关信息// 发送 HTTP 请求并接收服务器的响应
BOOL bSend = HttpSendRequestEx(hRequest, &buffersIn, &buffersOut, dwFlags, dwContext);if (bSend) {// 请求发送成功并接收到服务器的响应,可以继续处理服务器响应数据// 使用 InternetReadFile 函数读取服务器返回的数据
} else {// 请求发送失败,可以根据 GetLastError 获取错误代码进行相应的处理
}// 关闭句柄,释放资源
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);

ReadFile

ReadFile 是 Windows API 中的一个函数,位于 kernel32.dll 中,用于从文件、管道、字符设备等对象中读取数据。

BOOL ReadFile(HANDLE       hFile,LPVOID       lpBuffer,DWORD        nNumberOfBytesToRead,LPDWORD      lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped
);

参数说明:

  • hFile: 要读取的文件、管道或设备的句柄。
  • lpBuffer: 指向用于存储读取数据的缓冲区。
  • nNumberOfBytesToRead: 要读取的字节数。
  • lpNumberOfBytesRead: 指向一个变量,用于接收实际读取的字节数。
  • lpOverlapped: 用于异步操作的 OVERLAPPED 结构体指针,可设置为 NULL 表示使用同步操作。

ReadFile 函数用于从指定的文件、管道或设备中读取数据,并将读取的数据存储到指定的缓冲区中。如果读取成功,则返回 TRUE,并通过 lpNumberOfBytesRead 参数返回实际读取的字节数。如果读取失败,则返回 FALSE,并可以通过调用 GetLastError 函数获取错误代码。

使用方法示例:

#include <Windows.h>int main() {HANDLE hFile = CreateFile(L"C:\\path\\to\\file.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE) {// 处理文件打开失败的情况return -1;}char buffer[1024];DWORD bytesRead = 0;if (ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL)) {// 读取成功,bytesRead 中存储了实际读取的字节数// 可以对 buffer 中的数据进行处理} else {// 读取失败,可通过 GetLastError 获取错误代码}CloseHandle(hFile);return 0;
}

InternetWriteFile

InternetWriteFile 是 Windows API 中的一个函数,位于 WinINet 库中,用于向服务器发送 HTTP 请求的主体数据。

BOOL InternetWriteFile(HINTERNET hFile,LPCVOID   lpBuffer,DWORD     dwNumberOfBytesToWrite,LPDWORD   lpdwNumberOfBytesWritten
);

参数说明:

  • hFile: HTTP 请求句柄,通过调用 HttpOpenRequest 函数返回。
  • lpBuffer: 指向包含要发送的数据的缓冲区指针。
  • dwNumberOfBytesToWrite: 要发送的数据的字节数。
  • lpdwNumberOfBytesWritten: 指向一个变量,用于接收实际写入的字节数。

InternetWriteFile 函数用于向服务器发送 HTTP 请求的主体数据,即请求体。在调用该函数时,需要先调用 HttpOpenRequest 函数创建一个 HTTP 请求句柄,并通过 InternetConnect 函数建立到服务器的连接。

使用方法示例:

HINTERNET hInternet = InternetOpen(...); // 打开一个 Internet 会话
HINTERNET hConnect = InternetConnect(hInternet, ...); // 建立到服务器的连接
HINTERNET hRequest = HttpOpenRequest(hConnect, ...); // 创建一个 HTTP 请求句柄const char* requestData = "This is the request data.";
DWORD requestDataSize = strlen(requestData);
DWORD bytesWritten = 0;// 发送 HTTP 请求的主体数据
BOOL bWrite = InternetWriteFile(hRequest, requestData, requestDataSize, &bytesWritten);if (bWrite) {// 请求体数据发送成功,可以继续处理服务器的响应数据
} else {// 请求体数据发送失败,可以根据 GetLastError 获取错误代码进行相应的处理
}// 关闭句柄,释放资源
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);

HttpEndRequest

HttpEndRequest 是 Windows API 中的一个函数,位于 WinINet 库中,用于结束 HTTP 请求并接收服务器的响应。

BOOL HttpEndRequest(HINTERNET hRequest,LPINTERNET_BUFFERS lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext
);

参数说明:

  • hRequest: HTTP 请求句柄,通过调用 HttpOpenRequest 函数返回。

  • lpBuffersOut: 指向一个 INTERNET_BUFFERS 结构体的指针,用于接收服务器响应数据的缓冲区。

  • dwFlags
    

    : 指定结束请求的标志,可以为以下常量的组合:

    • INTERNET_NO_CALLBACK: 不使用回调函数。
    • INTERNET_FLAG_KEEP_CONNECTION: 在完成请求后保持与服务器的连接。
    • INTERNET_FLAG_SECURE: 使用 SSL 连接。
    • 其他标志,具体可参考官方文档。
  • dwContext: 用户定义的上下文参数,将在异步操作时传递给回调函数。

HttpEndRequest 函数用于结束 HTTP 请求并接收服务器的响应。在调用该函数后,可以通过 lpBuffersOut 参数接收服务器返回的数据。在调用 HttpSendRequestHttpSendRequestEx 函数后,应该使用 HttpEndRequest 函数来结束请求,以确保请求被正确发送给服务器并接收响应。

WriteFile

WriteFile 是 Windows API 中的一个函数,位于 kernel32.dll 中,用于向文件、管道、字符设备等对象中写入数据。

BOOL WriteFile(HANDLE       hFile,LPCVOID      lpBuffer,DWORD        nNumberOfBytesToWrite,LPDWORD      lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped
);

参数说明:

  • hFile: 要写入数据的文件、管道或设备的句柄。
  • lpBuffer: 指向包含要写入数据的缓冲区。
  • nNumberOfBytesToWrite: 要写入的字节数。
  • lpNumberOfBytesWritten: 指向一个变量,用于接收实际写入的字节数。
  • lpOverlapped: 用于异步操作的 OVERLAPPED 结构体指针,可设置为 NULL 表示使用同步操作。

WriteFile 函数用于向指定的文件、管道或设备中写入数据,并将指定的数据写入到缓冲区中。如果写入成功,则返回 TRUE,并通过 lpNumberOfBytesWritten 参数返回实际写入的字节数。如果写入失败,则返回 FALSE,并可以通过调用 GetLastError 函数获取错误代码。

使用方法示例:

#include <Windows.h>int main() {HANDLE hFile = CreateFile(L"C:\\path\\to\\file.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE) {// 处理文件打开失败的情况return -1;}const char* dataToWrite = "Hello, WriteFile!";DWORD dataSize = strlen(dataToWrite);DWORD bytesWritten = 0;if (WriteFile(hFile, dataToWrite, dataSize, &bytesWritten, NULL)) {// 写入成功,bytesWritten 中存储了实际写入的字节数} else {// 写入失败,可通过 GetLastError 获取错误代码}CloseHandle(hFile);return 0;
}

SetEvent

SetEvent 是 Windows API 中的一个函数,位于 kernel32.dll 中,用于将指定的事件对象的状态设置为 signaled(即触发状态)。

BOOL SetEvent(HANDLE hEvent
);

参数说明:

  • hEvent: 要设置为 signaled 状态的事件对象的句柄。

SetEvent 函数用于将指定的事件对象的状态设置为 signaled。如果事件对象的初始状态为非 signaled(未触发状态),则调用 SetEvent 函数后,事件对象的状态会变为 signaled(触发状态),从而可以通知等待该事件对象的线程,使其继续执行。

使用方法示例:

#include <Windows.h>int main() {// 创建一个自动重置的事件对象HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);if (hEvent == NULL) {// 处理事件对象创建失败的情况return -1;}// 等待事件对象的状态变为 signaledWaitForSingleObject(hEvent, INFINITE);// 继续执行其他操作CloseHandle(hEvent);return 0;
}

WinHttp简介:

什么是WinHttp?

Microsoft Windows HTTP Services (WinHTTP) 提供服务器支持的 HTTP/2 和 1.1 Internet 协议的高级接口。 WinHTTP 主要用于与 HTTP 服务器通信的服务器应用程序在基于服务器的方案中。

API的使用步骤如下:

在这里插入图片描述

封装类

编译器使用的是vs2019,然后json库和编码转换以及类之间的通信使用的是Qt的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XQgpmpKA-1693216132597)(…\Image\企业微信截图_20230814161504.png)]

WinHttpRequest类是提供给调用者使用的,WinHttpThread则是实际发送http请求的地方;

大致流程如下:

main
WinHttpRequest
WinHttpThread

调用者将所需参数传入winHttpRequest中,WinHttpRequest将参数转换后传入WinHttpThread中,如果指定的是异步则会创建一个线程,并将此线程传入线程池中,如果不是则会同步堵塞当前线程。在WinHttpThread中http处理完成后则会将信息传回到WinHttpRequest中,由WinHttpRequest通知调用者http返回的结果;

WinHttpRequest.h

#pragma once
#include <QObject>
#include <QThreadPool>
#include "WinHttpThread.h"class WinHttpRequest :public QObject
{Q_OBJECT
public:enum CONNECTIO_ACTION{        SYNCHRONOUS,ASYNCHRONOUS,};Q_ENUM(CONNECTIO_ACTION)WinHttpRequest(QObject *parent=nullptr);~WinHttpRequest();static WinHttpRequest* getInstance();/// <summary>/// 开始Http请求/// </summary>/// <param name="url">资源路径</param>/// <param name="headetContentType">告知服务端文本格式</param>/// <param name="model">请求谓词</param>/// <param name="requestType">用来表示每一个http请求的枚举值</param>/// <param name="params">body中传入的参数</param>/// <param name="connection">同步或异步</param>void httpRequest(const QString url, const QString headetContentType = "", const WinHttpThread::HttpRequestMode model = WinHttpThread::GET, const WinHttpThread::HttpRequestType requestType = WinHttpThread::HTTP_REQUEST_LOGIN, const QVariantMap params = {}, CONNECTIO_ACTION connection = ASYNCHRONOUS);
public: signals:	void sigHttpRequestReply(int code, WinHttpThread::HttpRequestType requestType, QByteArray data);   
private:QThreadPool m_threadPool;
};

WinHttpRequest.cpp

#include "WinHttpRequest.h"
#include <iostream>
#include <strsafe.h>WinHttpRequest::WinHttpRequest(QObject* parent):QObject(parent)
{m_threadPool.setMaxThreadCount(3);
}WinHttpRequest::~WinHttpRequest()
{m_threadPool.clear();m_threadPool.waitForDone(3000);
}WinHttpRequest* WinHttpRequest::getInstance()
{static WinHttpRequest winHttpRequest;return &winHttpRequest;
}void WinHttpRequest::httpRequest(const QString url, const QString headetContentType, const WinHttpThread::HttpRequestMode model, const WinHttpThread::HttpRequestType requestType, const QVariantMap params, CONNECTIO_ACTION connection) {if (connection == ASYNCHRONOUS) {WinHttpThread* thread = new WinHttpThread(url, headetContentType, model, requestType, params);connect(thread, &WinHttpThread::sigHttpRequested, this, [=](int code, WinHttpThread::HttpRequestType type, QByteArray recev) {qDebug() << "code:" << code << " type" << type << " recev" << QString::fromUtf8(recev);});m_threadPool.start(thread);}else {WinHttpThread thread(url, headetContentType, model, requestType, params);WinHttpThread::MsgData msgData;if (thread.doWork(msgData)) {qDebug() << "code:" << msgData.statuscode << " type:" << msgData.reqType << " recev" << QString::fromUtf8(msgData.data);}}	
}

WinHttpThread.h

#pragma once
#include <qobject.h>
#include <QThread>
#include <QRunnable>
#include <QObject>
#include <QVariantMap>
#include <QJsonDocument>
#include <windows.h>
#include <winhttp.h>
#include <QString>
#include <QThreadPool>
#include <mutex>#pragma comment (lib,"Winhttp")typedef struct URLData {QString hostName;QString resourceUrl;int port;URLData() {hostName = "";resourceUrl = "";port = INTERNET_DEFAULT_HTTP_PORT;}
}URLData_t;class WinHttpThread :public QObject,public QRunnable
{Q_OBJECT
public:enum HttpRequestMode {GET,POST,HEAD,PUT,DELETE_N,CONNECT,OPTIONS,TRACE,DEFAULT};Q_ENUM(HttpRequestMode)enum HttpRequestType {HTTP_REQUEST_LOGIN,HTTP_REQUEST_USERCONFIG,HTTP_REQUEST_GETPAGE};Q_ENUM(HttpRequestType)typedef struct MsgData {DWORD statuscode;HttpRequestType reqType;QByteArray data;}MsgData_t;WinHttpThread() = delete;WinHttpThread(const QString url, const QString headetContentType = "", const HttpRequestMode model = GET, const HttpRequestType requestType = HTTP_REQUEST_LOGIN, const QVariantMap params = {});~WinHttpThread();//时机处理http请求的地方bool doWork(MsgData& data);
public:signals:void sigHttpRequested(int code, HttpRequestType type, QByteArray recev);
protected:void init();void run();bool analyseUrl(const QString& url);template <typename T>void setRawHeader(QString key, T value);	
private:void addHeaderToHttp(HINTERNET &hRequest);LPCWSTR getReqModel(HttpRequestMode reqModel);void ReleaseHandle();private:HINTERNET m_heSession;HINTERNET m_hConnect;HINTERNET m_hRequest;bool isInit = false;QMap<QString, QString> m_map;//headerQVariantMap m_params;//bodyQString m_url = "";QString m_headerContentType = "";HttpRequestMode m_model;HttpRequestType m_requestType;	URLData_t m_urlData;const LPCWSTR m_appName = L"vlive";std::mutex m_mutex;QByteArray data;
};

WinHttpThread.cpp


#include "WinHttpThread.h"WinHttpThread::WinHttpThread(const QString url, const QString headetContentType, const HttpRequestMode model, const HttpRequestType requestType, const QVariantMap params):m_url(url),m_headerContentType(headetContentType),m_model(model),m_requestType(requestType), m_params(params)
{isInit = analyseUrl(m_url);//此处设置http头部内容m_map.insert("browser_kernel", "1.6.2");m_map.insert("device", "DDF935926350BAF0372FB0058DB22687CC75F03580B02FCDBC5D6A0B");m_map.insert("version", "1.6.2.0");m_map.insert("Content-type", headetContentType);
}WinHttpThread::~WinHttpThread()
{	ReleaseHandle();
}void WinHttpThread::init()
{
}void WinHttpThread::run()
{	MsgData data;if (doWork(data)) {emit sigHttpRequested(data.statuscode, data.reqType, data.data);}	ReleaseHandle();	
}bool WinHttpThread::analyseUrl(const QString& url)
{QUrl qurl(url);DWORD error;if (!qurl.isValid()) {qDebug() << "no vailed url." << url;return false;}m_urlData.hostName = qurl.host();m_urlData.resourceUrl = qurl.path();QString str = qurl.scheme();if (str == "https") {m_urlData.port = INTERNET_DEFAULT_HTTPS_PORT;}else if (str == "http") {m_urlData.port = INTERNET_DEFAULT_HTTP_PORT;}else {qDebug() << "unkonw url." << url;return false;}return true;
}void WinHttpThread::addHeaderToHttp(HINTERNET& hRequest)
{if (!hRequest) {qDebug() << "hRequest is null...";return;}QMap<QString,QString>::const_iterator iteral;BOOL re = FALSE;QString data = "";std::wstring dataC = L"";DWORD error;for (iteral = m_map.cbegin(); iteral != m_map.cend(); iteral++) {data = iteral.key() + ": " + iteral.value();dataC = data.toStdWString();re = WinHttpAddRequestHeaders(hRequest, dataC.c_str(), dataC.size(), WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);if (re) {error = GetLastError();qDebug() << "header:" << data << "error:" << error;			}}
}LPCWSTR WinHttpThread::getReqModel(HttpRequestMode reqModel)
{switch (reqModel) {case GET:return L"GET";break;case POST:return L"POST";break;case PUT:return L"PUT";break;case DELETE_N:return L"DELETE";break;default:return L"";break;}
}void WinHttpThread::ReleaseHandle()
{if (m_mutex.try_lock()) {if (m_hRequest)   WinHttpCloseHandle(m_hRequest);if (m_hConnect)   WinHttpCloseHandle(m_hConnect);if (m_heSession)   WinHttpCloseHandle(m_heSession);m_mutex.unlock();}	
}bool WinHttpThread::doWork(MsgData& msgData) {if (!isInit)return false;DWORD error;m_heSession = WinHttpOpen(m_appName, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);if (!m_heSession) {error = GetLastError();qDebug() << "WinHttpOpen:" << "error:" << error;}LPCWSTR model = getReqModel(m_model);m_hConnect = WinHttpConnect(m_heSession, m_urlData.hostName.toStdWString().c_str(), m_urlData.port, 0);if (!m_hConnect) {error = GetLastError();qDebug() << "WinHttpConnect error:" << error;ReleaseHandle();return false;}m_hRequest = WinHttpOpenRequest(m_hConnect, model, m_urlData.resourceUrl.toStdWString().c_str(), NULL, WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);if (!m_hRequest) {error = GetLastError();qDebug() << "WinHttpConnect error:" << error;ReleaseHandle();return false;}//bodyQByteArray byte = "";if (!m_params.isEmpty()) {byte = QJsonDocument::fromVariant(m_params).toJson().data();}//init httpheaderaddHeaderToHttp(m_hRequest);std::string strB = byte.toStdString();//send && init bodyif (!WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (LPVOID)strB.c_str(), strB.size(), strB.size(), 0)) {error = GetLastError();qDebug() << "WinHttpSendRequest error:" << error;ReleaseHandle();return false;}if (!WinHttpReceiveResponse(m_hRequest, 0)) {error = GetLastError();qDebug() << "WinHttpReceiveResponse error:" << error;ReleaseHandle();return false;}//get status codeDWORD statusCode;DWORD dwSize = sizeof(statusCode);DWORD recevicedSize;WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode, &dwSize, WINHTTP_NO_HEADER_INDEX);//READ dataLPSTR pszOutBuffer;QByteArray data;do {dwSize = 0;if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize)) {error = GetLastError();qDebug() << "WinHttpQueryDataAvailable error:" << error;ReleaseHandle();return false;}else {pszOutBuffer = new char[dwSize + 1];if (!pszOutBuffer) {qDebug() << "out memory...";dwSize = 0;}else {ZeroMemory(pszOutBuffer, dwSize + 1);//读取处理的数据编码为uincode可能会乱码,需要转为utf-8。此处不转换,有外部转换if (!WinHttpReadData(m_hRequest, (LPVOID)pszOutBuffer,dwSize, &recevicedSize)) {error = GetLastError();qDebug() << "WinHttpQueryDataAvailable error:" << error;ReleaseHandle();delete[] pszOutBuffer;return false;}else {data.append(pszOutBuffer);}delete[] pszOutBuffer;}}} while (dwSize > 0);msgData.statuscode = statusCode;msgData.data = data;msgData.reqType = m_requestType;return true;
}

例子

 	QVariantMap params;params.insert("name", "hqluo");	WinHttpRequest::getInstance()->httpRequest("https://www.baidu.com", "application/json", WinHttpThread::HttpRequestMode::GET,WinHttpThread::HttpRequestType::HTTP_REQUEST_GETPAGE, 		params,WinHttpRequest::ASYNCHRONOUS);
//此处我们将http的请求体中的内容设置为{"name":"hqluo"},并且告知服务端数据格式为json格式,以及模式设置为异步模式

这篇关于WinInet和winHttp库使用简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/177296

相关文章

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi

关于pandas的read_csv方法使用解读

《关于pandas的read_csv方法使用解读》:本文主要介绍关于pandas的read_csv方法使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录pandas的read_csv方法解读read_csv中的参数基本参数通用解析参数空值处理相关参数时间处理相关

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求