|
|
【代码】WinHttp的基本用法 |
一派护法 十九级 |
无关的参数全部传递NULL。 【示例1:下载一个png图像,并保持到磁盘上】 #include <stdio.h> #include <Windows.h> #include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
void main() { HINTERNET hSession = WinHttpOpen(L"My Test", NULL, NULL, NULL, NULL); HINTERNET hConnect = WinHttpConnect(hSession, L"localhost", 81, NULL); // 可用宏INTERNET_DEFAULT_HTTP_PORT表示默认的http端口号: 80
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET",
L"test/images/background.png", NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); WinHttpSendRequest(hRequest, NULL, NULL, NULL, NULL, NULL, NULL); WinHttpReceiveResponse(hRequest, NULL);
FILE *fp; fopen_s(&fp, "image.png", "wb"); // 注意, 这里的b选项非常重要 DWORD dwSize; DWORD dwRead = 0; while (WinHttpQueryDataAvailable(hRequest, &dwSize), dwSize > 0) { char *buffer = (char *)malloc(dwSize * sizeof(char)); WinHttpReadData(hRequest, buffer, dwSize, &dwRead); fwrite(buffer, dwSize, 1, fp); free(buffer); } printf("%d bytes written.\n", dwRead); fclose(fp);
WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); }
|
一派护法 十九级 |
【示例2:下载一个HTML页面,并保存到磁盘上】 #include <stdio.h> #include <Windows.h> #include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
void main() { HINTERNET hSession = WinHttpOpen(L"My Test", NULL, NULL, NULL, NULL); HINTERNET hConnect = WinHttpConnect(hSession, L"localhost", INTERNET_DEFAULT_HTTP_PORT, NULL); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"test/range.html", NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); WinHttpSendRequest(hRequest, NULL, NULL, NULL, NULL, NULL, NULL); WinHttpReceiveResponse(hRequest, NULL);
FILE *fp; fopen_s(&fp, "page.html", "wb"); // 注意, 这里的b选项非常重要 DWORD dwSize; DWORD dwRead = 0; while (WinHttpQueryDataAvailable(hRequest, &dwSize), dwSize > 0) { char *buffer = (char *)malloc(dwSize * sizeof(char)); WinHttpReadData(hRequest, buffer, dwSize, &dwRead); fwrite(buffer, dwSize, 1, fp); free(buffer); } printf("%d bytes written.\n", dwRead); fclose(fp);
WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); }
|
一派护法 十九级 |
【示例3:加载一个HTML页面到内存中并显示到屏幕上,不写入磁盘】 #include <stdio.h> #include <Windows.h> #include <winhttp.h> #pragma comment(lib, "winhttp.lib") void main() { HINTERNET hSession = WinHttpOpen(L"My Test", NULL, NULL, NULL, NULL); HINTERNET hConnect = WinHttpConnect(hSession, L"msdn.microsoft.com", INTERNET_DEFAULT_HTTP_PORT, NULL); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"en-us/library/windows/desktop/ms536160(v=vs.85).aspx", NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); WinHttpSendRequest(hRequest, NULL, NULL, NULL, NULL, NULL, NULL); WinHttpReceiveResponse(hRequest, NULL); char *content = NULL; DWORD dwSize; DWORD dwRead = 0; DWORD dwBufSize = 0; while (WinHttpQueryDataAvailable(hRequest, &dwSize), dwSize > 0) { content = (char *)realloc(content, dwBufSize + dwSize + 1); WinHttpReadData(hRequest, content + dwBufSize, dwSize, &dwRead); dwBufSize += dwSize; } content[dwBufSize] = '\0'; // 手动添加字符串结束标记 puts(content); // 输出 free(content); // 注意: content中保存的内容的编码与网页完全相同 // 因此如果是UTF-8编码且其中有中文的话,必须进行编码转换才能正确显示 // 一般转换为UTF-16(wchar_t)或ANSI // 如果要将内容送入MSXML6解析器, 就必须转换为UTF-16编码才行 WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); } 【运行结果】
|
一派护法 十九级 |
【示例4:加载一幅网络图像到内存中并显示到窗口上,不写入磁盘】 #include <tchar.h> #include <Windows.h> #include <gdiplus.h> #include <winhttp.h>
#pragma comment(lib, "gdiplus.lib") #pragma comment(lib, "winhttp.lib")
using namespace Gdiplus;
Image *img;
void LoadPicture(void) { HINTERNET hSession = WinHttpOpen(L"My Test", NULL, NULL, NULL, NULL); HINTERNET hConnect = WinHttpConnect(hSession, L"zh.arslanbar.net", INTERNET_DEFAULT_HTTP_PORT, NULL); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"Files/TopicImages/2012-7/8_2012-7-13_121400_609-318482.jpg", NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); WinHttpSendRequest(hRequest, NULL, NULL, NULL, NULL, NULL, NULL); WinHttpReceiveResponse(hRequest, NULL);
HGLOBAL hMem = NULL; char *content = NULL; DWORD dwSize; DWORD dwRead = 0; DWORD dwBufSize = 0; while (WinHttpQueryDataAvailable(hRequest, &dwSize), dwSize > 0) { // 这里改用GlobalAlloc分配内存 if (hMem == NULL) hMem = GlobalAlloc(GMEM_MOVEABLE, dwSize); else hMem = GlobalReAlloc(hMem, dwBufSize + dwSize, GMEM_MOVEABLE); content = (char *)GlobalLock(hMem); // 获得分配的内存首地址 WinHttpReadData(hRequest, content + dwBufSize, dwSize, &dwRead); GlobalUnlock(hMem); dwBufSize += dwSize; } WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession);
// 转换为Stream对象并创建图像 IStream *is; CreateStreamOnHGlobal(hMem, TRUE, &is); img = new Image(is); is->Release(); }
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { Graphics *graphics; HDC hdc; PAINTSTRUCT ps; TCHAR szText[100];
switch (uMsg) { case WM_CREATE: LoadPicture(); // 当窗口创建时加载图像 break; case WM_DESTROY: delete img; // 当窗口关闭时删除图像 PostQuitMessage(0); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps);
// 显示图像 graphics = new Graphics(hdc); graphics->DrawImage(img, 2, 20); delete graphics;
// 显示图像尺寸 _stprintf_s(szText, TEXT("Size: %ux%u"), img->GetWidth(), img->GetHeight()); TextOut(hdc, 2, 2, szText, _tcslen(szText));
EndPaint(hWnd, &ps); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return FALSE; }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // 初始化GDI+ GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// 注册窗口类 WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wcex.hInstance = hInstance; wcex.lpfnWndProc = WndProc; wcex.lpszClassName = TEXT("MainWindow"); // 窗口类名称 wcex.lpszMenuName = NULL; wcex.style = NULL; RegisterClassEx(&wcex);
// 创建并显示窗口 HWND hWnd = CreateWindow(wcex.lpszClassName, TEXT("Display Remote Picture"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) return 1; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
// 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
GdiplusShutdown(gdiplusToken); return msg.wParam; }
|
一派护法 十九级 |
【运行结果】
|
一派护法 十九级 |
【示例5:提交POST数据】 【C++代码】 #include <stdio.h> #include <Windows.h> #include <winhttp.h> #pragma comment(lib, "winhttp.lib") void main() { char *szData = "user=admin&id=49&operation=update&text=abc中文"; wchar_t *szHeader = L"Content-type: application/x-www-form-urlencoded"; DWORD dwDataSize = strlen(szData); DWORD dwHeaderSize = wcslen(szHeader); HINTERNET hSession = WinHttpOpen(L"My Test", NULL, NULL, NULL, NULL); HINTERNET hConnect = WinHttpConnect(hSession, L"localhost", INTERNET_DEFAULT_HTTP_PORT, NULL); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"test/requests/?id=203¶m", NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); // 设置为POST方式 WinHttpAddRequestHeaders(hRequest, szHeader, dwHeaderSize, WINHTTP_ADDREQ_FLAG_ADD); // 添加请求头 WinHttpSendRequest(hRequest, NULL, NULL, szData, dwDataSize, dwDataSize, NULL); // 发送POST数据 WinHttpReceiveResponse(hRequest, NULL); char *content = NULL; DWORD dwSize; DWORD dwRead = 0; DWORD dwBufSize = 0; while (WinHttpQueryDataAvailable(hRequest, &dwSize), dwSize > 0) { content = (char *)realloc(content, dwBufSize + dwSize + 1); WinHttpReadData(hRequest, content + dwBufSize, dwSize, &dwRead); dwBufSize += dwSize; } content[dwBufSize] = '\0'; puts(content); free(content); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); system("pause"); } 【PHP代码】 <?php echo '[GET]', PHP_EOL; print_r($_GET); echo PHP_EOL, '[POST]', PHP_EOL; print_r($_POST); ?> 【运行结果】
|
一派护法 十九级 |
【示例6:以UTF8方式提交POST数据,然后以wchar_t格式显示网页内容】 #include <stdio.h> #include <Windows.h> #include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
// 将UTF16(wchar_t)转换成UTF8, 用后必须释放空间 char *ToUTF8(wchar_t *data) { int cbSize = WideCharToMultiByte(CP_UTF8, NULL, data, -1, NULL, NULL, NULL, NULL); char *buffer = new char[cbSize]; WideCharToMultiByte(CP_UTF8, NULL, data, -1, buffer, cbSize, NULL, NULL); return buffer; }
// 将UTF8转换成UTF16, 用后必须释放空间 wchar_t *ToUTF16(char *data) { int cbSize = MultiByteToWideChar(CP_UTF8, NULL, data, -1, NULL, NULL); wchar_t *buffer = new wchar_t[cbSize]; MultiByteToWideChar(CP_UTF8, NULL, data, -1, buffer, cbSize); return buffer; }
void main() { char *szData = ToUTF8(L"user=admin&id=49&operation=update&text=abc中文"); wchar_t *szHeader = L"Content-type: application/x-www-form-urlencoded"; DWORD dwDataSize = strlen(szData); DWORD dwHeaderSize = wcslen(szHeader);
HINTERNET hSession = WinHttpOpen(L"My Test", NULL, NULL, NULL, NULL); HINTERNET hConnect = WinHttpConnect(hSession, L"localhost", INTERNET_DEFAULT_HTTP_PORT, NULL); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"test/requests/?id=203¶m", NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); // 设置为POST方式 WinHttpAddRequestHeaders(hRequest, szHeader, dwHeaderSize, WINHTTP_ADDREQ_FLAG_ADD); WinHttpSendRequest(hRequest, NULL, NULL, szData, dwDataSize, dwDataSize, NULL); WinHttpReceiveResponse(hRequest, NULL);
// 由于这里不是显示图像, 因此直接用C语言的内存分配函数就行了 // 无需使用GlobalAlloc char *content = NULL; DWORD dwSize; DWORD dwRead = 0; DWORD dwBufSize = 0; while (WinHttpQueryDataAvailable(hRequest, &dwSize), dwSize > 0) { content = (char *)realloc(content, dwBufSize + dwSize + 1); WinHttpReadData(hRequest, content + dwBufSize, dwSize, &dwRead); dwBufSize += dwSize; } if (content != NULL) content[dwBufSize] = '\0'; // 网页内容的编码是UTF8, 将其转换为wchar_t(UTF16), 然后显示到控制台中 wchar_t *w_content = ToUTF16(content); free(content); // 在控制台中显示wchar_t字符串不能用printf或cout, 否则中文和很多其他语言文字不能正常输出 HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); WriteConsoleW(hConsoleOutput, w_content, wcslen(w_content), NULL, NULL); delete[] w_content; delete[] szData; WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession);
system("pause"); } 【运行结果】 和示例5一样。
|
一派护法 十九级 |
【示例7:加载一幅网络图像到内存中并显示到对话框的图像控件中,不写入磁盘】 代码请参阅:https://zh.arslanbar.net/post.php?t=23893 【运行效果】
|
|
|
|