免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5526 | 回复: 10
打印 上一主题 下一主题

[函数] select返回-1的问题 [复制链接]

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-02-22 15:42 |只看该作者 |倒序浏览

描述符集合中监听多个socket,长连接。

当一个客户端的连接断掉后,

select会返回-1,errno=9  Bad file descriptor。

请问这种情况怎么处理?

如何判断是哪个socket断开了连接,从而在select监视的描述符集合中,将该断开的socket移除?


论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2016-02-23 09:54 |只看该作者
回复 1# lewy7


    客户端断掉应该是read = 0吧,在读事件里面close和fd_clr就可以了

recv.JPG (33.05 KB, 下载次数: 81)

recv.JPG

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
3 [报告]
发表于 2016-02-23 11:11 |只看该作者
回复 2# lxyscls


    试了一下,当select返回-1时,FD_ISSET并不能得到断开连接的socket,这样我就不知道要去recv哪个socket了。

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2016-02-23 11:20 |只看该作者
回复 3# lewy7


    在你的读事件里面处理recv = 0的情况,而不是select返回-1的时候

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
5 [报告]
发表于 2016-02-23 11:31 |只看该作者
回复 4# lxyscls


    socket集合里面都是长连接,select阻塞监听这些socket的事件,如果有可读的事件到来,才会去read有事件到来的socket;
    也就是说select阻塞直到有事件到来,否则不会主动去read集合里的socket的。

    现在的问题就是select返回-1后,找不到断开连接的socket。

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2016-02-23 11:47 |只看该作者
回复 5# lewy7


    客户端关断,没有读事件上来吗?

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
7 [报告]
发表于 2016-02-23 11:56 |只看该作者
回复 6# lxyscls


    没有可读事件,select直接就返回-1,然后errno就是9了。

    ERRORS
       EBADF  An  invalid  file descriptor was given in one of the sets.  (Perhaps a file descriptor that was already closed, or one on which an error
              has occurred.)

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2016-02-23 12:24 |只看该作者
回复 7# lewy7


    贴代码

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
9 [报告]
发表于 2016-02-23 12:42 |只看该作者
回复 8# lxyscls
  1.         int    clientArray[256];
  2.         int    clientConnected;
  3.         int    listenFd ,clientFd;
  4.         fd_set fds;
  5.         listenFd = socket_listen(socketFile);
  6.        
  7.         while(1){
  8.                 FD_ZERO(&fds);
  9.                 FD_SET(listenFd, &fds);
  10.                 maxfdsn = listenFd;
  11.                
  12.                 for( i=0;i<clientConnected;i++ ){
  13.                         FD_SET(clientArray[i], &fds);
  14.                         if( clientArray[i] > maxfdsn )
  15.                                 maxfdsn = clientArray[i];
  16.                 }
  17.                
  18.                 ret = select(maxfdsn+1, &fds, NULL, NULL, NULL);
  19.                 if(ret<0){
  20.                         //*********
  21.                         for (i = 0; i < clientConnected; i++) {
  22.             if (FD_ISSET(clientArray[i], &fds)) {
  23.                     //返回-1的时候可读事件没有触发
  24.                                         memset(&data,0,sizeof( jss_monitor_t ));
  25.                                         recvLen = read(clientArray[i],&data,sizeof( jss_monitor_t));
  26.                                         sprintf(sysBuf,  "select return error fd %d len {%d} \n",clientArray[i],recvLen);
  27.                                         write(logFd,sysBuf,strlen(sysBuf));
  28.             }
  29.           }
  30.                         continue;
  31.                 }

  32.                
  33.                 if(FD_ISSET(listenFd,&fds)){
  34.                         memset(&un,0,sizeof(struct sockaddr_un));
  35.                         addrLen = sizeof(struct sockaddr_un);
  36.                         clientFd = accept(listenFd,(struct sockaddr *)&un,  (socklen_t *)&addrLen);
  37.                         if (clientFd <= 0) {
  38.                                 continue;
  39.                         }
  40.                        
  41.                         setsockopt(clientFd ,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
  42.                         //add to overlook array
  43.                         clientArray[clientConnected] = clientFd;
  44.                         clientConnected++;
  45.                 }

  46.                 // check every client fd in the set
  47.         for (i = 0; i < clientConnected; i++) {
  48.             if (FD_ISSET(clientArray[i], &fds)) {
  49.                         memset(&data,0,sizeof( jss_monitor_t ));
  50.                         recvLen = read(clientArray[i],&data,sizeof( jss_monitor_t));
  51.                        
  52.                         if (recvLen <= 0) {
  53.                                         FD_CLR(clientArray[i], &fds);
  54.                                         close(clientArray[i]);
  55.                                         for( j=i;j<clientConnected;j++){
  56.                                                         clientArray[ j ]=clientArray[ j+1 ];
  57.                                         }
  58.                                         close(clientArray[i]);
  59.                                         clientConnected--;
  60.                                         break;
  61.                         }
  62.                   }//end while read

  63.         }
  64.                
  65.         }// end death loop
复制代码

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2016-02-23 12:54 |只看该作者
本帖最后由 lxyscls 于 2016-02-23 12:56 编辑

回复 9# lewy7

  1.         for (i = 0; i < clientConnected; i++) {
  2.             if (FD_ISSET(clientArray[i], &fds)) {
  3.                         memset(&data,0,sizeof( jss_monitor_t ));
  4.                         recvLen = read(clientArray[i],&data,sizeof( jss_monitor_t));
  5.                         
  6.                         if (recvLen <= 0) {
  7.                                         FD_CLR(clientArray[i], &fds);
  8.                                         close(clientArray[i]);
  9.                                         for( j=i;j<clientConnected;j++){
  10.                                                         clientArray[ j ]=clientArray[ j+1 ];
  11.                                         }
  12.                                         close(clientArray[i]);
  13.                                         clientConnected--;
  14.                                         break;
  15.                         }
  16.                   }//end while read

  17.         }
  18.                
  19.         }// end death loop
复制代码
你多close了一次,这次close了一个正确的fd,然后又去select,所以就bad file descriptor了

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP