首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

非阻塞摸下select,recv使用有关问题

2012-06-22 
非阻塞摸下select,recv使用问题场景描述:通讯上的问题,client在接收server数据时,偶尔会发生EAGAIN的错误。

非阻塞摸下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

代码片段:

C/C++ code
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 */



[解决办法]
如果select表示socket可读,那么再recv应该不会返回EAGAIN


select返回时,可能会修改它的参数(集合、超时时间),最好在循环内部重新赋值
[解决办法]
汗,你看过APUE+UNP吗.

默认select就支持0-1024个fd,但你可以配置系统文件修改这个大小,百度一下就知道。

I/O复用开发去读读开源代码,看看标准做法是什么,自己造轮子没意义。

热点排行