2016-09-07 79 views
0

我试图为从accept()函数返回的客户端套接字设置套接字选项。但他们没有正确设置。从accept()返回的客户端套接字设置sockopt()

我的目标是在特定的闲置时间后超时。但服务器应该仍然能够接受其他客户端连接。

下面是我设置套接字选项的代码。你能提出什么问题吗?

while ((new_sock_fd = accept(socket_fd, (struct sockaddr *) &cli_addr, &clilen)) > 0) 
{ 
    if (new_sock_fd < 0) 
     printf("Accept Error"); 
    else 
    { 
     struct timeval timeout;  
     timeout.tv_sec = 10; 
     timeout.tv_usec = 0; 
     if (setsockopt(new_sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) 
      error("setsockopt failed\n"); 
     if (setsockopt(new_sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) 
      error("setsockopt failed\n"); 
     pthread_create(&thread, NULL, client_handler, (void *) (intptr_t)new_sock_fd); //intptr_t is big enough to hold the integer prt 
    } 
} 
+1

你怎么知道选项没有被设置? 'setsockopt()'失败,出现错误? 'getsocktop()'返回你不期待的值吗?插座的行为是否与预期不同?如果是这样,怎么样?这个代码运行在什么平台上?在大多数平台上,'SO_RCVTIMEO'和'SO_SENDTIMEO'的确将'timeval'结构作为输入。但在Windows上,他们需要一个“DWORD”。 –

+1

另外,你的'Accept Error'消息永远不会被报告,因为当'new_socket_fd> 0'时你的循环只进入循环体。如果你想对'accept()'进行错误处理,你应该把它移到循环中。 –

回答

1

我的目标是 活动的特定时间后超时客户端。 [...]你可以请建议什么时候错了..?

我怀疑是什么错误是你误解了SO_RCVTIMEO和SO_SNDTIMEO打算做什么。从man page

SO_RCVTIMEO和SO_SNDTIMEO指定接收或发送超时 直到报告错误。该参数是一个结构timeval。如果在此段时间内输入或输出功能块为 ,并且已发送或接收数据 ,则该函数的返回值将为传输的数据量的 ;如果没有数据传输并且已经达到超时,则返回-1,并且将errno设置为EAGAIN 或者EWOULDBLOCK或者EINPROGRESS(用于连接(2)),就像套接字 被指定为非阻塞一样。如果超时设置为零(默认为 ),那么操作永远不会超时。

...但它听起来像你想要的是TCP连接在一定的时间后自动关闭,TCP连接上没有流量,这与强制呼叫发送是不一样的()或recv()在指定的时间后返回。

如果您正在寻找的是一种关闭空闲TCP连接的机制,则可以通过在套接字上发送或接收数据时记录当前时间来实现该功能。在稍后的时间(例如,在send()或recv()超时之后),您可以从当前时间减去您记录的最近一次记录的流量;如果差值大于您的空闲超时值,请自己在套接字上调用close()。

+0

或者,只需使用'select()'或'epoll()'来实现超时。将套接字置于非阻塞模式,然后1)在读取之前,使用超时轮询可读性; 2)如果使用'EAGAIN'或'EWOULDBLOCK'发送失败,则通过超时轮询可写性。如果任一操作超时,请关闭连接。 –