2012-03-16 46 views
0

我在非阻塞套接字(unix下的c語言)中有recv()函數的問題 我已經設置套接字爲非阻塞下面的代碼(服務器程序):socket編程-recv()函數

int x; 
x=fcntl(listen_sd,F_GETFL,0); 
fcntl(listen_sd,F_SETFL,x | O_NONBLOCK); 

當我呼叫recv(),如果消息可用,它會返回消息的長度,如果沒有,則會阻止!

我起訴了我的代碼中的選擇功能。

while(1) 
     { 
      /**********************************************/ 
      /* Receive data on this connection until the */ 
      /* recv fails with EWOULDBLOCK. If any other */ 
      /* failure occurs, we will close the   */ 
      /* connection.        */ 
      /**********************************************/ 
      rc = recv(i, buffer, sizeof(buffer), 0); 
      if (rc < 0) 
      { 
     if(errno == EAGAIN||errno == EWOULDBLOCK) 
     { 
     printf("no message\n"); 
     break; 
     } 

       perror(" recv() failed"); 
       close_conn = TRUE; 

      } 

      /**********************************************/ 
      /* Check to see if the connection has been */ 
      /* closed by the client      */ 
      /**********************************************/ 
      if (rc == 0) 
      { 
      printf("connection closed\n"); 
      close_conn = TRUE; 
      break; 


      } 

      /**********************************************/ 
      /* Data was recevied       */ 
      /**********************************************/ 
      len = rc; 
      printf(" %d bytes received\n", len); 
     } 

如果客戶端發送消息並沒有關閉連接,那麼服務器的recv的第一次調用()得到消息,並在第二個呼叫被封鎖(換言之的recv()不返回EWOULDBLOCK錯誤可言!!) 爲什麼?

+0

在這裏使用UDP套接字 – hroptatyr 2012-03-16 10:14:31

回答

3

我的猜測是,你正在將O_NONBLOCK調用放入你用於listen的套接字中。但是一旦您撥打accept,您將獲得另一個代表連接的套接字。根據平臺的不同,這個新的套接字可能會也可能不具有從另一個套接字繼承的O_NONBLOCK。

引用我的Linux的man accept

在Linux上,通過accept()返回不繼承文件狀態標誌,如從監聽套接字O_NONBLOCKO_ASYNC新的插座。這種行爲不同於規範的BSD套接字實現。便攜式程序不應該依賴來繼承或不傳遞文件狀態標誌,並且總是明確地設置從accept()返回的套接字上的所有必需標誌

+0

thanks.so你的意思是我必須調用fcntl()的每個套接字返回接受? – Mushtu 2012-03-16 10:27:06

+0

是的,就是這樣。或者如果你使用的是linux,你可以調用GNU特有的'accept4()'函數,它接收一個額外的參數併爲你做。 – rodrigo 2012-03-16 10:30:29

+0

你的猜測是正確的。我打電話fcntl()爲每個連接和它的作品。感謝這麼多 – Mushtu 2012-03-16 10:36:56