关于使用HttpSendRequestEx多线程发送http post的问题

acinonyx 2010-04-11 04:39:31
希望各位大虾指教一番,分数奉上,问题是这样的:
我在使用wininet异步发送http post,多线程调用时,希望每个线程能得到自己发送的结果。
但实际情况当使用多线程调用函数是,某个线程得到的返回结果可能是其他线程发送的,目前自己还找不出原因,希望哪位高手指教一下,不胜感谢!
代码如下:

#include <windows.h>
#include <wininet.h>
#include <stdio.h>

typedef struct {
DWORD dwNumBytesComplete;
HANDLE hConnectedEvent;
HANDLE hRequestCompleteEvent;
HINTERNET hConnect;
HINTERNET hRequest;
int ntype;
}REQUEST_CONTEXT;

static void __stdcall Callback(HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpStatusInfo,
DWORD dwStatusInfoLen)
{
REQUEST_CONTEXT *httpreq = (REQUEST_CONTEXT*)dwContext;
//printf("Callback dwInternetStatus: %d Context: %d\n", dwInternetStatus, dwContext);

switch(httpreq->ntype)
{
case 1: // Connection handle
if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
{
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
httpreq->hConnect = (HINTERNET)pRes->dwResult;
//printf("Connect handle created\n");
SetEvent(httpreq->hConnectedEvent);
}
break;
case 2: // Request handle
switch(dwInternetStatus)
{
case INTERNET_STATUS_HANDLE_CREATED:
{
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
httpreq->hRequest = (HINTERNET)pRes->dwResult;
//HINTERNET hConnect = (HINTERNET)pRes->dwResult;
//printf("Request handle created\n");

}
break;
case INTERNET_STATUS_REQUEST_SENT:
{
DWORD *lpBytesSent = (DWORD*)lpStatusInfo;
//printf("Bytes Sent: %d\n", *lpBytesSent);
httpreq->dwNumBytesComplete += *lpBytesSent;
}
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
{
INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
//printf("Function call finished\n");
//printf("dwResult: %d\n", pAsyncRes->dwResult);
//printf("dwError: %d\n", pAsyncRes->dwError);
SetEvent(httpreq->hRequestCompleteEvent);
}
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
//printf("Receiving Response\n");
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
{
DWORD *dwBytesReceived = (DWORD*)lpStatusInfo;
//printf("Received %d\n", *dwBytesReceived);
}

}
}
}

int sendhttppost(const char *server, int nport, const char *webpath,
const char *postdata, int npostlen, char *respage, int *nmaxreslen)
{
int iret = 0;
int ireslen = 0;
DWORD dwNumKSent;
DWORD dwNumKToSend;
BOOL bAllDone = FALSE;
HINTERNET hInstance = NULL;
REQUEST_CONTEXT httpreq;

httpreq.dwNumBytesComplete = 0;
dwNumKToSend = npostlen;
httpreq.hConnect = NULL;
httpreq.hRequest = NULL;

httpreq.hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
httpreq.hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

hInstance = InternetOpen("async_http", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
if (hInstance == NULL)
{
printf("InternetOpen failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}

if (InternetSetStatusCallback(hInstance, (INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK)
{
printf("InternetSetStatusCallback failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}

httpreq.ntype = 1; //connect
httpreq.hConnect = InternetConnect(hInstance, server, nport, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD)&httpreq);
if (httpreq.hConnect == NULL)
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("InternetConnect failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}
WaitForSingleObject(httpreq.hConnectedEvent, HTTP_REQUEST_TIMEOUT_WINDOWS);
}

httpreq.ntype = 2; //Request
httpreq.hRequest = HttpOpenRequest(httpreq.hConnect, "POST", webpath, NULL, NULL, (LPCSTR*)"*/*",
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, (DWORD)&httpreq);//2);
if (httpreq.hRequest == NULL)
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("HttpOpenRequest failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}
WaitForSingleObject(httpreq.hRequestCompleteEvent, HTTP_REQUEST_TIMEOUT_WINDOWS);
}

INTERNET_BUFFERS IntBuff;
FillMemory(&IntBuff, sizeof(IntBuff), 0);
IntBuff.dwStructSize= sizeof(IntBuff);
IntBuff.dwBufferTotal = 1024 * dwNumKToSend;
//IntBuff.lpcszHeader = "Content-Type: text/text\r\n";
IntBuff.lpcszHeader = "Content-Type: application/x-www-form-urlencoded";
IntBuff.dwHeadersLength = lstrlen(IntBuff.lpcszHeader);

httpreq.ntype = 2; //Request
if (!HttpSendRequestEx(httpreq.hRequest, &IntBuff, NULL, 0, (DWORD)&httpreq))
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("HttpSendRequestEx failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}
//printf("HttpSendRequestEx called successfully\n");
WaitForSingleObject(httpreq.hRequestCompleteEvent, HTTP_REQUEST_TIMEOUT_WINDOWS);
}

for (dwNumKSent = 0; dwNumKSent < dwNumKToSend; dwNumKSent++)
{
DWORD dwBytesWritten;

if(!InternetWriteFile(httpreq.hRequest, postdata, 2048, &dwBytesWritten))
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("InternetWriteFile failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}
else
{
//printf("InternetWriteFile completing asynchronously\n");
WaitForSingleObject(httpreq.hRequestCompleteEvent, HTTP_REQUEST_TIMEOUT_WINDOWS);
}
}
}

//printf("Calling HttpEndRequest\n");

if (!HttpEndRequest(httpreq.hRequest, NULL, HSR_INITIATE, 2))
{
if (GetLastError() == ERROR_IO_PENDING)
{
printf("HttpEndRequest called\n");

WaitForSingleObject(httpreq.hRequestCompleteEvent, HTTP_REQUEST_TIMEOUT_WINDOWS);
}
else
{
printf("HttpEndRequest failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}
}

//printf("------------------- Read the response -------------------\n");
do
{
INTERNET_BUFFERS InetBuff;
FillMemory(&InetBuff, sizeof(InetBuff), 0);
InetBuff.dwStructSize = sizeof(InetBuff);
InetBuff.lpvBuffer = respage + ireslen;
InetBuff.dwBufferLength = *nmaxreslen - ireslen;

printf("Calling InternetReadFileEx\n");

if (!InternetReadFileEx(httpreq.hRequest, &InetBuff, 0, 2))
{
if (GetLastError() == ERROR_IO_PENDING)
{
printf("Waiting for InternetReadFile to complete\n");

WaitForSingleObject(httpreq.hRequestCompleteEvent, HTTP_REQUEST_TIMEOUT_WINDOWS);
}
else
{
printf("InternetReadFileEx failed, error %d\n", GetLastError());
iret = -1;
goto EXIT_SENDPOST;
}
}

ireslen += InetBuff.dwBufferLength;
respage[ireslen] = 0;

if (InetBuff.dwBufferLength == 0)
bAllDone = TRUE;

} while (bAllDone == FALSE);
*nmaxreslen = ireslen;

//printf("\n\n------------------- Request Complete ----------------\n");

EXIT_SENDPOST:
if(httpreq.hRequest)
{
if(!InternetCloseHandle(httpreq.hRequest))
printf("InternetCloseHandle(httpreq.hRequest) error\n");
}
if(httpreq.hConnect)
{
if(!InternetCloseHandle(httpreq.hConnect))
printf("InternetCloseHandle(httpreq.hConnect) error\n");
}
if(hInstance)
{
if(!InternetCloseHandle(hInstance))
printf("InternetCloseHandle(hInstance) error\n");
}

return iret;
}

...全文
969 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
baoyz 2010-04-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 oyljerry 的回复:]
Callback 中判断一下是哪个线程的callback,如增加一个线程ID属性等,sendhttppost等可以增加一个现场ID来区分,
[/Quote]

一般是这样的。
liumenghappy 2010-04-14
  • 打赏
  • 举报
回复
帮顶一下
oyljerry 2010-04-11
  • 打赏
  • 举报
回复
Callback 中判断一下是哪个线程的callback,如增加一个线程ID属性等,sendhttppost等可以增加一个现场ID来区分,

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧