2016-04-27 246 views
0

我發現了一些關於如何做的提示,但我不明白如何使用setsockopt。我有一個無限的while循環調用recv,我想超時並且close(cli_socket)如果客戶端在5秒內不發送任何東西。套接字recv的設置超時TCP

如果客戶端只發送整個預期消息的一部分,我想重置計時器並給他5秒鐘。

currentry我有這樣的:

while((cut = buffer.find("\r\n")) == -1) 
     { 
      struct timeval tv; 
      tv.tv_sec = 5; 
      setsockopt(cli_socket, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); 
      recv(cli_socket, tmpBuffer, 100, 0); 
      buffer += tmpBuffer; 
      memset(tmpBuffer, 0, 100); 
     } 
+0

你'setsockopt'通話似乎好於我,這對我的作品。你看到了什麼行爲,它與你期望的有什麼不同?我注意到你不檢查'recv()'的返回值,這確實讓我懷疑你期望如果超時會發生什麼。 – Dolda2000

+0

我想關閉連接,如果超時 – lllook

回答

3

您應該測試recvbreak你的循環的回報,如果它是EAGAINEWOULDBLOCK

EAGAIN或EWOULDBLOCK
的插槽上都標非阻塞並且接收操作將會阻塞,或者接收超時已經設置,並且在數據收到之前超時已過期

struct timeval tv = {5, 0}; 
setsockopt(cli_socket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval)); 

while((cut = buffer.find("\r\n")) == -1) 
{ 
    int numBytes = recv(cli_socket, tmpBuffer, 100, 0)); 

    /// Edit: recv does not return EAGAIN else, it return -1 on error. 
    /// and in case of timeout, errno is set to EAGAIN or EWOULDBLOCK 

    if (numBytes <= 0) 
    { 
     // nothing received from client in last 5 seconds 
     break; 
    } 

    buffer.append(tmpBuffer, numBytes); 
} 

您還可以使用select函數,而不是那麼複雜的使用方法:

while((cut = buffer.find("\r\n")) == -1) 
{ 
    timeval timeout = { 5, 0 }; 
    fd_set in_set; 

    FD_ZERO(&in_set); 
    FD_SET(cli_socket, &in_set); 

    // select the set 
    int cnt = select(cli_socket + 1, &in_set, NULL, NULL, &timeout); 

    if (FD_ISSET(cli_socket, &in_set)) 
    { 
     int numBytes = recv(cli_socket, tmpBuffer, 100, 0)); 
     if (numBytes <= 0) 
     { 
      // nothing received from client 
      break; 
     } 

     buffer.append(tmpBuffer, numBytes); 
    } 
    else 
    { 
     // nothing received from client in last 5 seconds 
     break;  
    } 
} 
+0

民意調查比選擇好得多。 – SergeyA

+0

謝謝!我知道select()方法,我成功地使用了,我的意圖是學習如何使用setsockopt超時 – lllook

+0

還有一個問題,上面的代碼真的重置超時後,我至少收到了什麼? – lllook