我正在开发一个9p服务器,它非常像一个nfs服务器。随后的安装和卸载不会导致套接字描述符文件泄漏,因为我可以关闭套接字。但是,在以下情形中,服务器不会正确清理并关闭套接字。方案是,当机器A的客户端从服务器机器安装FS时。然后由于某种原因,机器A重新启动或关闭。如果发生这种情况,我希望服务器清理工作并关闭套接字但由于某种原因它会阻塞read()。我认为read()应该在连接关闭时返回0,但它不会。我假设这是因为没有发生正确的tcp终止,所以服务器正在等待来自客户端的一些数据。这是我服务器的伪代码
while(1){
n = read(sockfd, buffer, 4); //4 is protocol header that specifies the size
if ( n == 0 ) break;
/* iteratively read the rest of bytes until the incoming message ends */
}
cleanup(); // close socket and some other tasks
但是,当服务器在读取时阻塞时客户端重新启动时,没有任何反应。什么是最好的解决方法?有些人建议运行一个单独的线程来检查连接,但这太复杂了。我相信必须有更快的方式
答案 0 :(得分:2)
当客户端关闭时,客户端上的操作系统会终止所有TCP连接。但是当客户端崩溃或关闭时,或者当客户端和服务器之间的路径某处出现网络问题时,则无法向服务器传递信息,并且可能会在read()
呼叫中阻止服务器永远。
有两种可能的解决方案。您可以使用标准TCP保持活动探测器,也可以实现应用程序级别运行状况检查。
为了理解什么是TCP keepalive(我们将调用keepalive),你只需要读取名称:保持TCP活着。这意味着您将能够检查连接的套接字(也称为TCP套接字),并确定连接是否仍在运行或是否已损坏......
当你想要你的应用程序使用TCP保持活动时,只需设置套接字选项(缺少错误检查):
int optval = 1;
socklen_t optlen = sizeof(optval);
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
TCP keep alive很容易使用,但它取决于操作系统配置,应用程序无法设置自己的超时,因为它们是可配置的系统范围。
当您需要特定于应用程序的超时以进行断开连接检测时,请使用应用程序级别机制。有很多方法可以实现它。这个想法是定期发送一段无用的数据,并假设在没有收到连接时会破坏连接。
答案 1 :(得分:0)
我想用最重要的方法来修改Zaboj Campula的好答案:超时。通常,您可以为任何套接字操作分配超时。典型值为30秒。这样就不需要在大多数时间保持活力。将在30秒内检测到连接失败。
有些人建议运行一个单独的线程来检查连接,但这太复杂了。
这不起作用,因为您的机器不知道连接已经消失。没有什么可以检查的。