非阻塞摸下select,recv使用问题
场景描述:
通讯上的问题,client在接收server数据时,偶尔会发生EAGAIN的错误。使用strace抓出来的显示基本相同,但红旗方面提供的帮助说可能是使用select后,套接字不在集合中了。现正在改代码,问题有两个:
1. 以下对EAGAIN的处理是否正确?
2. select后是否必须用FD_ISSET检测sockfd是否在fd_set集合中?如果FD_ISSET返回错误,该如何处理?原sockfd是否还可用?重建sockfd还是只需要重新清空fd_set,再使用select等待?
望高人解答!
strace片段:
17:09:12 send(1089, "\0\0\1$\2\10\0\0\nAAAAAAAAAA110101\0\0\0\0\0\0\0"..., 296, 0) = 296
17:09:12 recv(1089, 0xbfff0090, 4000, 0) = -1 EAGAIN (Resource temporarily unavailable)
17:09:12 select(1090, [1088 1089], NULL, NULL, {3, 0}) = 1 (in [1088], left {3, 0})
17:09:12 recv(1089, 0xbfff0090, 4000, 0) = -1 EAGAIN (Resource temporarily unavailable)
17:09:12 close(1089) = 0
代码片段:
while(nLen < nMsgLen) { FD_ZERO(&r_fds); FD_SET(nSockfd, &r_fds); errno = 0; if ((tv.tv_sec > 0) || ((tv.tv_sec == 0) && (tv.tv_usec > 0))){ ret = select(nSockfd + 1, &r_fds, NULL, NULL, &tv); }else{ ret = select(nSockfd + 1, &r_fds, NULL, NULL, NULL); } if (ret < 0) { /* error */ return -1; }else if(ret == 0) { /* expired */ return -2; } [color=#FF0000]/** 增加对 FD_ISSET 返回值处理 **/[/color] /* recv data */ nRecvLen = recv(nSockfd, &pData[nLen], HSM_MAX_BUFFER_SIZE, 0); if(nRecvLen < 0) { /* error */ [color=#FF6600]if (EAGAIN == errno) { if ((tv.tv_sec > 0) || ((tv.tv_sec == 0) && (tv.tv_usec > 0))) { continue; } }[/color]/* 增加的对EAGAIN错误的处理 */ return -2; }else if (nRecvLen == 0) return -4; // peer close connection. nLen += nRecvLen; } /* while */