socket异步使用SELECT等待线程一多cpu占用100%

i777 2009-05-25 06:28:58
代码其实网络上大家说的使用异步connect,然后select等待的经典代码。
我做了一个扫描网络段的程序,同时开50个线程,连接50个IP,当碰到很多IP地址主机不存在(无响应),
那么我的大部分线程select都在等待,占用cpu就会到100【等待超时8秒】。
大家看怎么解决这个问题。(我想很多人都碰到过,不知道高手怎么解决)
谢谢!!!
函数代码见下【vc++的】:
int ScanerMain::SendAndRecv(char * host,int port,char *in, char *out,int out_len)
{
char *rBuffer; /** receiving buffer */
char *sBuffer; /** receiving buffer */
rBuffer = out;
sBuffer = in;
SOCKET sock; /** used socket */
sockaddr_in sock_host;
int n_recv;
sock_host.sin_family = AF_INET;
sock_host.sin_addr.s_addr = Resol(host);
sock_host.sin_port = htons((unsigned short)port);
if(!sock_host.sin_addr.s_addr)
{
return -1;
}
if (sock = socket(AF_INET, SOCK_STREAM, 0))
{
int TimeOut=TIME_OUT_SEC*1000; //设置发送超时3秒
if( setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
{
//printf("thread=%d exit where setsockopt fail...\r\n",iThead);
return -1;
}
if( setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
{
//printf("thread=%d exit where setsockopt fail...\r\n",iThead);
return -1;
}

WriteLog ("BEGING CONNECT %s\r\n",host);
////非阻塞模式
int ul = 1;
if(ioctlsocket(sock, FIONBIO, (unsigned long*)&ul)==SOCKET_ERROR)
return -1;
connect(sock,(struct sockaddr *)&sock_host, sizeof(sock_host));
{
WriteLog ("success CONNECT %s\r\n",host);
//select 模型,即设置超时
struct timeval timeout ;
fd_set r;

FD_ZERO(&r);
FD_SET(sock, &r);
timeout.tv_sec = TIME_OUT_SEC; //连接超时8秒
timeout.tv_usec =0;
int ret = select(0, 0, &r, 0, &timeout);
if ( ret <= 0 )
{
closesocket(sock);
return 0;
}
////恢复阻塞模式
ul = 0;
if(ioctlsocket(sock, FIONBIO, (unsigned long*)&ul)==SOCKET_ERROR)
return -1;
n_recv = Request(sock, sBuffer, rBuffer, out_len);
WriteLog ("finish CONNECT %s\r\n",host);
closesocket (sock);
return n_recv;
}
/*else
{
WriteLog ("failed CONNECT %s\r\n",host);
}*/
}
return -1;
}

多谢了
...全文
859 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lgycoder 2009-05-27
  • 打赏
  • 举报
回复
楼主,如果对方IP不存活,你又怎么能connect,这句就错了,又怎么能select
mfc168 2009-05-27
  • 打赏
  • 举报
回复
CPU 100%一般都是出现死循环造成
50个线程,select不会占用那么多cpu
sun007700 2009-05-27
  • 打赏
  • 举报
回复
你先开1个线程试下,跟踪看下代码,感觉应该不是select的问题,看cpu使用率;再开10个试下,看下cpu使用率,最后开50个。。
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 i777 的回复:]
我说select占着,是因为大部分ip不存活
我是用windbg全速运行然后看出来的,
线程堆栈都在select那里。
[/Quote]

多线程就没必要再select了啊?

while(1)
{
accept....
pthread_create(...)
...

}

保持这种思路就可以了
yanghehong 2009-05-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hairetz 的回复:]
引用 4 楼 i777 的回复:


多线程就没必要再select了啊?

while(1)
{
accept....
pthread_create(...)
...

}

保持这种思路就可以了
[/Quote]

多线程,每个线程一个file discriptor,是没必要select。不过用select应该也没问题。
BTW.楼主不是做服务器程序,不需要listen, accept...

- 千里孤行

i777 2009-05-25
  • 打赏
  • 举报
回复
我说select占着,是因为大部分ip不存活
我是用windbg全速运行然后看出来的,
线程堆栈都在select那里。
i777 2009-05-25
  • 打赏
  • 举报
回复
其实根本走不到request那里,因为对方ip不存活,那么下面语句就返回了。

int ret = select(0, 0, &r, 0, &timeout);
if ( ret <= 0 )
{
closesocket(sock);
return 0;
}
i777 2009-05-25
  • 打赏
  • 举报
回复
unsigned long ScanerMain::Request(SOCKET sock, char *request, char *buffer, int mSz)
{
int rSz=0; //each reply
int tSz=0; //total received
struct timeval tOut;
int res_select;
fd_set sock_set;

send(sock,request,strlen(request),0);
memset(buffer,0,mSz);
do
{
rSz=recv(sock,buffer+tSz,mSz-tSz,0);
tSz+=rSz;
FD_ZERO(&sock_set);
FD_SET(sock,&sock_set);
tOut.tv_sec=TIME_OUT_SEC;
tOut.tv_usec=TIME_OUT_SEC;
}
while( (tSz<mSz) && (rSz!=0) && (res_select=select(sock+1,&sock_set,NULL,NULL,&tOut)) && (res_select != -1 ) );
return tSz;
}
yanghehong 2009-05-25
  • 打赏
  • 举报
回复
应该不是select 耗掉CPU

你这句代码具体做了什么?
n_recv = Request(sock, sBuffer, rBuffer, out_len);

可能大伙看了你的Request的实现,更好说


- 千里孤行

4,356

社区成员

发帖
与我相关
我的任务
社区描述
通信技术相关讨论
社区管理员
  • 网络通信
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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