2016-04-27 158 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