亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: select返回-1的問(wèn)題 [打印本頁(yè)]

作者: lewy7    時(shí)間: 2016-02-22 15:42
標(biāo)題: select返回-1的問(wèn)題

描述符集合中監(jiān)聽(tīng)多個(gè)socket,長(zhǎng)連接。

當(dāng)一個(gè)客戶端的連接斷掉后,

select會(huì)返回-1,errno=9  Bad file descriptor。

請(qǐng)問(wèn)這種情況怎么處理?

如何判斷是哪個(gè)socket斷開了連接,從而在select監(jiān)視的描述符集合中,將該斷開的socket移除?



作者: lxyscls    時(shí)間: 2016-02-23 09:54
回復(fù) 1# lewy7


    客戶端斷掉應(yīng)該是read = 0吧,在讀事件里面close和fd_clr就可以了

recv.JPG (33.05 KB, 下載次數(shù): 100)

recv.JPG

作者: lewy7    時(shí)間: 2016-02-23 11:11
回復(fù) 2# lxyscls


    試了一下,當(dāng)select返回-1時(shí),F(xiàn)D_ISSET并不能得到斷開連接的socket,這樣我就不知道要去recv哪個(gè)socket了。
作者: lxyscls    時(shí)間: 2016-02-23 11:20
回復(fù) 3# lewy7


    在你的讀事件里面處理recv = 0的情況,而不是select返回-1的時(shí)候
作者: lewy7    時(shí)間: 2016-02-23 11:31
回復(fù) 4# lxyscls


    socket集合里面都是長(zhǎng)連接,select阻塞監(jiān)聽(tīng)這些socket的事件,如果有可讀的事件到來(lái),才會(huì)去read有事件到來(lái)的socket;
    也就是說(shuō)select阻塞直到有事件到來(lái),否則不會(huì)主動(dòng)去read集合里的socket的。

    現(xiàn)在的問(wèn)題就是select返回-1后,找不到斷開連接的socket。
作者: lxyscls    時(shí)間: 2016-02-23 11:47
回復(fù) 5# lewy7


    客戶端關(guān)斷,沒(méi)有讀事件上來(lái)嗎?
作者: lewy7    時(shí)間: 2016-02-23 11:56
回復(fù) 6# lxyscls


    沒(méi)有可讀事件,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.)


作者: lxyscls    時(shí)間: 2016-02-23 12:24
回復(fù) 7# lewy7


    貼代碼
作者: lewy7    時(shí)間: 2016-02-23 12:42
回復(fù) 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的時(shí)候可讀事件沒(méi)有觸發(fā)
  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
復(fù)制代碼

作者: lxyscls    時(shí)間: 2016-02-23 12:54
本帖最后由 lxyscls 于 2016-02-23 12:56 編輯

回復(fù) 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
復(fù)制代碼
你多close了一次,這次close了一個(gè)正確的fd,然后又去select,所以就bad file descriptor了


作者: lewy7    時(shí)間: 2016-02-23 14:14
本帖最后由 lewy7 于 2016-02-23 14:17 編輯

回復(fù) 10# lxyscls


    原來(lái)如此,非常感謝。我原來(lái)只盯著select的返回值了,然后man到select的

RETURN VALUE
       On success, select() and pselect() return the number of file descriptors contained in the three returned descriptor sets (that  is,  the  total
       number  of bits that are set in readfds, writefds, exceptfds) which may be zero if the timeout expires before anything interesting happens.  On
       error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined, so do not rely on their contents after an  error.

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.)

看到EBADF,一直想把這個(gè)錯(cuò)誤的fd找出來(lái)。




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2