一般在LINUX服务器应用,在多线程编程中用recv非阻塞模式同时接受属于各自描述符的网络数据。因为大量的数据同时进来,recv可能会出现阻塞状态,并且极有可能完全阻塞从而导致线程阻塞。(不过有一种情况,就是client端给再次给服务器发送数据时,可能会触发阻塞中的recv接受返回,但是概率极小)。
这会使相应的线程永久阻塞得不到释放,运行一段时间最终将耗尽系统内存以及描述符资源,最终导致系统瘫痪。
根本的错误原因还没发找到,暂时只能先绕开问题,选择其他方法。经多天测试发现,将recv非阻塞模式换成阻塞模式可解决问题,用select模型代替recv非阻塞模式问题也得到解决。
原长生错误代码如下
for(i=0; i < 3; i ++)
{
if(recv(sockfd,&loginmsg, sizeof(loginmsg), MSG_DONTWAIT) > 0) //设置非阻塞recv模式
{//处理登陆事件
}
sleep(1);
}
这段代码是在线程中执行的,一个来一个连接开一个线程处理,recv虽设为非阻塞模式,但是在连接很多的情况下,却有可能阻塞。不得其解。
修改代码后:
LoginInfo buff;
memset(&buff, 0, sizeof(buff));
fd_set fdrr;
struct timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;
FD_ZERO(&fdrr);
FD_SET(fd_A[id], &fdrr);
if (select(fd_A[id] + 1, &fdrr, NULL, NULL, &tv) <= 0)
{
flag = -1;
}
if (FD_ISSET(fd_A[id],&fdrr))
{
if (recv(fd_A[id], &buff, sizeof(buff), 0) > 0)
{
//处理登陆事件 }
}
不会再出现问题了。
本人在redhat 5.0上运行代码。问题最根本原因仍未知,有大侠知道者望能赐教。