rc : Asynchronous http post
来源:互联网 发布:手机自动排班软件 编辑:程序博客网 时间:2024/06/06 08:58
同步HttpSendRequest执行时,会阻塞住。
在程序退出时,强杀线程问题很多. 不只是内存泄漏. 退出的时机不同,有时还会崩溃。
在被杀线程中使用主线程中的类成员e.g. map, 如果被杀时,正在操作那个map, 在主线程map free的时候崩溃了。
用http同步+退出程序时土法杀http线程的方法,问题多多。
还是得用优雅的异步http操作才行.
异步post的资料
Asynchronous Example Application (Windows) - MSDN
http://support.microsoft.com/kb/275046
#include<windows.h>#include<wininet.h>#include<iostream> // for cout, endlusing namespace std;HANDLE hConnectedEvent, hRequestOpenedEvent, hRequestCompleteEvent;HINTERNET hInstance, hConnect, hRequest;char *lpszUrl, *lpszServer;BOOL bAllDone = FALSE;BOOL bVerbose = FALSE;void __stdcall Callback(HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpStatusInfo, DWORD dwStatusInfoLen);void main(int argc, char *argv[]){ if (argc != 3) { if ((argc == 4) && (argv[3][0] == 'v')) bVerbose = TRUE; else { cout << "Usage: asynchttp <server> <url> [v]" << endl; cout << " <server> is the hostname of the http server" << endl; cout << " <url> is the url of the object you are requesting (without the hostname)" << endl; cout << " 'v' for verbose output" << endl << endl; cout << " Example: asynchttp www.domain.com /docs/readme.htm v" << endl; return; } } lpszServer = argv[1]; lpszUrl = argv[2]; hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hRequestOpenedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hInstance = InternetOpen("asynchttp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC); // ASYNC Flag if (hInstance == NULL) { cout << "InternetOpen failed, error " << GetLastError(); return; } // Setup callback function if (InternetSetStatusCallback(hInstance, (INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK) { cout << "InternetSetStatusCallback failed, error " << GetLastError(); return; } // First call that will actually complete asynchronously even // though there is no network traffic hConnect = InternetConnect(hInstance, lpszServer, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); // Connection handle's Context if (hConnect == NULL) { if (GetLastError() != ERROR_IO_PENDING) { cout << "InternetConnect failed, error " << GetLastError(); return; } // Wait until we get the connection handle WaitForSingleObject(hConnectedEvent, INFINITE); } // Open the request // 如果使用同步http操作, 主要是在HttpOpenRequest处,阻塞住. hRequest = HttpOpenRequest(hConnect, "GET", lpszUrl, NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 2); // Request handle's context if (hRequest == NULL) { if (GetLastError() != ERROR_IO_PENDING) { cout << "HttpOpenRequest failed, error " << GetLastError(); return; } // Wait until we get the request handle WaitForSingleObject(hRequestOpenedEvent, INFINITE); } if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) { if (GetLastError() != ERROR_IO_PENDING) { cout << "HttpSendRequest failed, error " << GetLastError(); return; } } if (bVerbose) { cout << "HttpSendRequest called successfully" << endl; cout.flush(); } WaitForSingleObject(hRequestCompleteEvent, INFINITE); cout << "------------------- Read the response -------------------" << endl; char lpReadBuff[256]; do { INTERNET_BUFFERS InetBuff; FillMemory(&InetBuff, sizeof(InetBuff), 0); InetBuff.dwStructSize = sizeof(InetBuff); InetBuff.lpvBuffer = lpReadBuff; InetBuff.dwBufferLength = sizeof(lpReadBuff) - 1; if (bVerbose) { cout << "Calling InternetReadFileEx" << endl; cout.flush(); } if (!InternetReadFileEx(hRequest, &InetBuff, 0, 2)) { if (GetLastError() == ERROR_IO_PENDING) { if (bVerbose) { cout << "Waiting for InternetReadFileEx to complete" << endl; cout.flush(); } WaitForSingleObject(hRequestCompleteEvent, INFINITE); } else { cout << "InternetReadFileEx failed, error " << GetLastError(); cout.flush(); return; } } lpReadBuff[InetBuff.dwBufferLength] = 0; cout << lpReadBuff; cout.flush(); if (InetBuff.dwBufferLength == 0) bAllDone = TRUE; } while (bAllDone == FALSE); cout << endl << endl << "------------------- Request Complete ----------------" << endl;}void __stdcall Callback(HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpStatusInfo, DWORD dwStatusInfoLen){ if (bVerbose) { cout << "Callback dwInternetStatus: " << dwInternetStatus << " Context: " << dwContext << endl; cout.flush(); } switch(dwContext) { case 1: // Connection handle if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED) { INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo; hConnect = (HINTERNET)pRes->dwResult; if (bVerbose) { cout << "Connect handle created" << endl; cout.flush(); } SetEvent(hConnectedEvent); } break; case 2: // Request handle switch(dwInternetStatus) { case INTERNET_STATUS_HANDLE_CREATED: { INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo; hRequest = (HINTERNET)pRes->dwResult; if (bVerbose) { cout << "Request handle created" << endl; cout.flush(); } SetEvent(hRequestOpenedEvent); } break; case INTERNET_STATUS_REQUEST_SENT: { DWORD *lpBytesSent = (DWORD*)lpStatusInfo; if (bVerbose) { cout << "Bytes Sent: " << *lpBytesSent << endl; cout.flush(); } } break; case INTERNET_STATUS_REQUEST_COMPLETE: { INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo; if (bVerbose) { cout << "Function call finished" << endl; cout << "dwResult: " << pAsyncRes->dwResult << endl; cout << "dwError: " << pAsyncRes->dwError << endl; cout.flush(); } SetEvent(hRequestCompleteEvent); } break; case INTERNET_STATUS_RECEIVING_RESPONSE: if (bVerbose) { cout << "Receiving Response" << endl; cout.flush(); } break; case INTERNET_STATUS_RESPONSE_RECEIVED: { DWORD *dwBytesReceived = (DWORD*)lpStatusInfo; if (*dwBytesReceived == 0) bAllDone = TRUE; if (bVerbose) { cout << "Received " << *dwBytesReceived << endl; cout.flush(); } } } }}
将MS例子中的回调,结合到类中就可以以c++方式异步httpPost。
将原始Demo重构一下
enum eHttpContext{ eHttpContext_Connection = 1, // Connection handle's Context eHttpContext_Request = 2, // Request handle's context };使用这2个enum的地方如下:
// First call that will actually complete asynchronously even // though there is no network traffic hConnect = InternetConnectA(hInstance, lpszServer, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, eHttpContext_Connection);
// Open the request // 如果使用同步http操作, 主要是在HttpOpenRequest处,阻塞住. hRequest = HttpOpenRequestA(hConnect, "GET", lpszUrl, NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, eHttpContext_Request);
if (!InternetReadFileEx(hRequest, &InetBuff, 0, eHttpContext_Request))
internet*ex函数的最后一个参数是 dwContext, 换成类指针,就可以实现c++方式的回调操作.
0 0
- rc : Asynchronous http post
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Android Asynchronous Http Client
- Spring3.2-quartz2.2.1集成执行任务调度
- mybatis向数据库传空值的问题
- Shopaholic
- 关于 hibernate SELECT command denied to user 的一种处理
- Android内存分析和调优(中)
- rc : Asynchronous http post
- commons-net FTP大文件上传
- 如何配置一个使用UPN登录的站点
- ScrollView中放ListView问题
- word2vec 中的数学原理详解(四)基于 Hierarchical Softmax 的模型
- 我奋斗了18年才和你坐在一起喝咖啡 原作者:麦子
- Random number系列-uniform distribution(是模拟其他分布随机变量的基础)
- HDU 2710 Max Factor (筛选求素数)
- Hadoop-2.4.1学习之Map任务源码分析(上)