用IOCP抓起网页时死机了

jiangfeng999 2009-11-02 09:34:08
我用IOCP写一个抓取网页的程序,可是一运行到线程函数中GetQueuedCompletionStatus这个位置时,几个线程就一直阻塞在这个位置,下不去了。url地址是从一个文件中读取出来的,大家看看这是为什么呢?


#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <afxmt.inl>
using namespace std;
#define DATA_BUFSIZE 1024*1024*10
#pragma comment(lib,"ws2_32")

#define OP_READ 1
#define OP_WRITE 2

static unsigned int nFileSerial=0;
typedef struct
{
OVERLAPPED Overlapped;
CHAR Buffer[DATA_BUFSIZE];
CHAR strUrl[100];
DWORD nRecvBytes;
int nOperationType;
} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;


typedef struct
{
SOCKET Socket;
struct sockaddr_in addr; // 服务器地址
} HOST_INFO_T;

HANDLE g_hCompletion;//完成端口
struct sockaddr_in servAddr;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);

void PostRequest(const char *pHostName,const char *pUrlAddress)
{
SOCKET cs;
char strRequest[1024];
cs = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==cs)
{
printf("创建套接字失败\n");
return ;
}
if(connect(cs,(sockaddr *)&servAddr,sizeof(servAddr))==SOCKET_ERROR)
{
printf("%d\n",WSAGetLastError());
return ;
}

HOST_INFO_T *pHostInfo;
LPPER_IO_OPERATION_DATA lpHandlerData;

pHostInfo = (HOST_INFO_T *)malloc(sizeof(HOST_INFO_T));
lpHandlerData=(PER_IO_OPERATION_DATA *)malloc(sizeof(PER_IO_OPERATION_DATA));

memset(strRequest,0,sizeof(strRequest));
sprintf_s(strRequest,"GET %s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\nConnection: close\r\n\r\n",pUrlAddress,pHostName); //取得HTTP报头

send(cs,strRequest,strlen(strRequest),0);
pHostInfo->Socket = cs;

CreateIoCompletionPort((HANDLE)&pHostInfo->Socket,g_hCompletion,(DWORD)pHostInfo,0);

// 投递一个接收请求
memset(lpHandlerData->Buffer,0,sizeof(lpHandlerData->Buffer));
lpHandlerData->nRecvBytes = 0;
lpHandlerData->nOperationType = OP_READ;
strcpy(lpHandlerData->strUrl,pUrlAddress);
WSABUF wsaBuf;
wsaBuf.len = 1024*10;
wsaBuf.buf = lpHandlerData->Buffer;
//memset(&(lpHandlerData->Overlapped),0,sizeof(OVERLAPPED));
DWORD nFlags=0;
DWORD dwTrans=0;
WSARecv(pHostInfo->Socket,&wsaBuf,1,&dwTrans,&nFlags,&(lpHandlerData->Overlapped),NULL);
}
void main(void)
{
HANDLE ThreadHandle[4];
SYSTEM_INFO SystemInfo;

DWORD ThreadID;
WSADATA wsaData;
DWORD Ret=0;
SOCKET cs;

vector<string> vUrlList;
char strHostName[50]="search.51job.com";
FILE *fp=fopen("E:\\test\\UrlList.TXT","r");
char strTemp[255];
while(!feof(fp))
{
memset(strTemp,0,sizeof(strTemp));
fgets(strTemp,sizeof(strTemp),fp);
strTemp[strlen(strTemp)-1]=0;
vUrlList.push_back(strTemp);
}
fclose(fp);


if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return;
}

cs = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==cs)
{
printf("创建套接字失败\n");
return ;
}

struct hostent *newHost;
newHost = gethostbyname(strHostName);
if(newHost==NULL)
{
printf("不能连通远程主机【%s】,%d\n",strHostName,GetLastError());
return;
}

char strIpAddress[20];
memset(strIpAddress,0,sizeof(strIpAddress));
strncpy(strIpAddress,inet_ntoa(*(in_addr *)newHost->h_addr_list[0]),sizeof(strIpAddress));
servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr=inet_addr(strIpAddress);
servAddr.sin_port=htons(80);

if((g_hCompletion=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0))==NULL)
{
printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError());
return;
}

GetSystemInfo(&SystemInfo);
for(DWORD i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
if ((ThreadHandle[i] = CreateThread(NULL, 0, ServerWorkerThread, (LPVOID)g_hCompletion,0, NULL)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
}
}


for(int k=0;k<vUrlList.size();k++)
{
PostRequest((const char *)strHostName,vUrlList[k].c_str());
}

WaitForMultipleObjects(4,ThreadHandle,true,INFINITE);
CloseHandle(ThreadHandle[0]);
CloseHandle(ThreadHandle[1]);
CloseHandle(ThreadHandle[2]);
CloseHandle(ThreadHandle[3]);
}

DWORD WINAPI ServerWorkerThread(LPVOID lpParam)
{
HOST_INFO_T *pHostInfo;
LPPER_IO_OPERATION_DATA lpHandlerData;
BOOL bOK=FALSE;
DWORD dwTrans=0;
// 得到完成端口对象句柄
HANDLE hCompletion = (HANDLE)lpParam;

while(true)
{
bOK = GetQueuedCompletionStatus(hCompletion,&dwTrans,(LPDWORD)&pHostInfo,(LPOVERLAPPED*)&lpHandlerData,INFINITE);
if (dwTrans==0 && (lpHandlerData->nOperationType==OP_READ || lpHandlerData->nOperationType==OP_WRITE))
{
SavHttpPage(lpHandlerData->Buffer);
fprintf(stderr,"成功抓取网页【%s】\n",lpHandlerData->strUrl);
closesocket(pHostInfo->Socket);
free(pHostInfo);
free(lpHandlerData);
continue;
}
DWORD dwflag=0;
switch (lpHandlerData->nOperationType)
{
case OP_READ:
WSABUF wsaData;
lpHandlerData->nRecvBytes+=dwTrans;
wsaData.buf = lpHandlerData->Buffer+lpHandlerData->nRecvBytes;
wsaData.len = 1024*10;
WSARecv(pHostInfo->Socket,&wsaData,1,&dwTrans,&dwflag,&lpHandlerData->Overlapped,NULL);
break;
case OP_WRITE:
break;
}
}
return 0;
}


...全文
152 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiangfeng999 2009-11-06
  • 打赏
  • 举报
回复
求教啊
jiangfeng999 2009-11-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cjianwen 的回复:]
WSARecv(pHostInfo->Socket,&wsaBuf,1,&dwTrans,&nFlags,&(lpHandlerData->Overlapped),NULL);


真牛, 返回值都不判断,你能保证一定成功吗?
[/Quote]
验证过了,有数据接收下来。这个程序只是一个例子,所以都没有做返回值的判断
jiangfeng999 2009-11-03
  • 打赏
  • 举报
回复
有人知道答案吗?
cjianwen 2009-11-02
  • 打赏
  • 举报
回复
IOCP 太神了,客户都用...
cjianwen 2009-11-02
  • 打赏
  • 举报
回复
WSARecv(pHostInfo->Socket,&wsaBuf,1,&dwTrans,&nFlags,&(lpHandlerData->Overlapped),NULL);


真牛, 返回值都不判断,你能保证一定成功吗?
WuXinyang 2009-11-02
  • 打赏
  • 举报
回复
友情UP
jiangfeng999 2009-11-02
  • 打赏
  • 举报
回复
没有人回答吗,自己顶一下
内容概要:本文系统梳理了多个科研领域的前沿研究与技术实现,重点涵盖FDTD方法中的完美匹配层(PML)研究,以及Matlab/Simulink在电磁、电力、控制、通信、信号处理、图像处理、路径规划、能源系统优化等领域的仿真与算法实现。文中列举了大量基于Matlab和Python的科研案例,如风电功率预测、负荷预测、无人机三维路径规划、电池系统故障诊断、雷达模拟、通信编码、微电网优化调度等,并强调结合智能优化算法(如粒子群、遗传算法、深度学习等)提升系统性能。同,提供了丰富的代码资源与仿真模型,涵盖永磁同步电机控制、逆变器设计、多智能体任务分配、虚拟电厂调度等复杂系统,助力科研人员快速开展复现实验与创新研究。; 适合人群:具备一定编程基础,熟悉Matlab/Python工具,从事电气工程、自动化、通信、人工智能、新能源、控制科学等相关领域研究的研发人员及研究生。; 使用场景及目标:① 学习并实现FDTD仿真中的PML边界条件以有效抑制数值反射;② 掌握Matlab/Simulink在多物理场建模、控制系统设计与优化算法中的综合应用;③ 借助提供的代码资源完成科研复现、课程设计、竞赛项目或工程原型开发; 阅读建议:此资源以科研实战为导向,不仅提供理论方法,更强调代码实现与仿真验证。建议读者结合自身研究方向,按目录顺序查阅相关模块,下载配套代码进行调试与二次开发,以达到学以致用、融会贯通的目的。

18,357

社区成员

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

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