C 检测客户端应用程序何时按顺序关闭连接

C 检测客户端应用程序何时按顺序关闭连接,c,sockets,server,client-server,C,Sockets,Server,Client Server,我正在开发一个9p服务器,它与nfs服务器非常相似。随后的装载和卸载不会导致套接字描述符文件泄漏,因为我能够关闭套接字。但是,在下面的场景中,服务器没有进行适当的清理并关闭套接字。场景是,当机器A上的客户端从服务器机器装载FS时。然后由于某种原因,机器A重新启动或关闭。如果发生这种情况,我希望服务器清理工作并关闭套接字,但由于某种原因,它会阻塞read()。我认为read()在连接关闭时应该返回0,但它没有返回。我假设这是因为没有发生正确的tcp终止,所以服务器正在等待来自客户端的一些数据。这是

我正在开发一个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

但是,当客户端在服务器阻塞读取时重新启动时,什么也不会发生。解决这个问题的最佳方法和最简单方法是什么?有些人建议运行一个单独的线程来检查连接,但这太复杂了。我相信一定有一种更快的方法

当客户端关闭时,客户端上的操作系统会终止所有TCP连接。但是,当客户端崩溃或关闭时,或者当客户端和服务器之间的路径某处出现网络问题时,则无法向服务器传递信息,并且服务器可能会在
read()
调用中永远被阻塞

有两种可能的解决办法。您可以使用标准TCP keep-alive探测器,也可以实现应用程序级运行状况检查

TCP保持活动状态 TCP保持活动状态的详细描述,例如:

为了理解TCP keepalive(我们称之为keepalive)的功能,您只需阅读名称:keep TCP alive。这意味着您将能够检查连接的套接字(也称为TCP套接字),并确定连接是否仍在运行或是否已断开

当您希望应用程序使用TCP保持活动状态时,只需设置套接字选项(缺少错误检查):

TCP keep alive易于使用,但它取决于操作系统配置,应用程序无法设置自己的超时,因为它们在系统范围内是可配置的

应用程序级健康检查
当需要断开连接检测的应用程序特定超时时,请使用应用程序级机制。有很多方法可以实现它。我们的想法是定期发送一段无用的数据,并假设连接在未收到数据时被破坏。

我想用最重要的方法来修改Zaboj Campula的好答案:超时。通常,您会为任何套接字操作分配一个超时。典型值为30秒。那样的话,大多数时候就不需要维持生命了。连接故障将在30秒内检测到

有些人建议运行一个单独的线程来检查连接,但这太复杂了


这不起作用,因为您的计算机不知道连接已断开。没有要检查的内容。

协议是否有某种心跳/ping消息?如果是这样,您可以使用它来考虑客户端在某个时间段内不发送ping /心跳的情况下丢失。在linux上是这样描述的。我的意思是,另一个线程只会向所有当前连接发送某种心跳消息。如果对等机没有回复,则假定它已崩溃。套接字超时将不起作用,因为这是一个已装入的FS。它不是那种随时都会收到请求的服务器类型。事实上,可能需要很长时间才能有人接触到这个挂载的FSF。构建应用程序级健康检查很简单。然而,我实际上无法访问客户端的源代码。协议中也未指定此健康检查,因此即使发送此无用消息,也可能导致客户端崩溃,因为客户端无法理解它。我想ping可以工作,但它并没有涵盖所有的可能性。我想知道NFS之类的东西是如何实现这种健康的check@Keeto:NFS是一个无状态协议,因此它在应用程序级别上没有可见的“连接”。原始NFS使用UDP作为传输协议,因此不需要释放连接。NFSv3可以使用TCP,NFS服务器实现TCP连接管理,例如HP/UX NFS守护程序在空闲6分钟时释放TCP连接。空闲意味着没有传出流量。但是没有客户端活动检测。如果客户端仍然处于活动状态,那么它可以建立一个新的连接,因为NFS是无状态的,所以请求是通过旧连接还是通过新连接传递都无关紧要。另一方面,9p是面向连接的,服务器和客户端都存储重要状态。我认为无状态是有利于NFS的一个非常重要的积极因素
int optval = 1;
socklen_t optlen = sizeof(optval);
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);