在不阻塞的情况下检测断开连接的客户端 (C)
Detecting a disconnected client without blocking (C)
我一直在玩弄 C 语言中的基本 client/server 通信,我正在尝试确定检测断开连接的客户端的最佳方法。我知道如果我想要一个阻塞解决方案,我可以简单地从 read() 分支出来。但是,在非阻塞上下文中,尤其是在网络中断而不是完全断开连接的情况下,read() 是否仍会及时检测到断开的连接?
现在我只是定期从客户端发送保持活动消息并检查服务器端超时,我想知道是否有更简洁的方法。
一般来说,您无法肯定地检测到未完全断开连接的客户端。
编辑:也就是说,没有通用的 are_you_still_there()
功能,也没有办法实现您可以始终依赖的快速交付功能 "no"既没有假阴性也没有假阳性的反应。
如果您使用的是无连接网络协议(即 UDP),那么您根本无法肯定地检测到客户端已永久消失。
编辑:TCP 在接收方未确认接收的情况下提供自动数据重传。相同数据的多次重新传输是可能的,在这种情况下,(重新)传输之间的超时会呈指数增长。在没有确认的情况下达到重传阈值次数或重传超时阈值后,TCP 子系统将认为连接断开,但这可能需要几分钟甚至几十分钟,具体取决于本地协议实现和参数。
如果 TCP 实现检测到连接中断,您可以依靠 read()
发出错误信号,无论是超时还是远程对等点强行切断连接。但是,如果您的 "timely" 概念与 TCP 实现的概念大不相同,则确保以 "timely" 方式将此类错误传递给应用程序可能很棘手或不可能。
人们通常通过使用 [edit: application-level] 超时来判断何时释放专用于服务客户端的资源,或者可能通过更高级别的资源来处理这个问题提供心跳信号或等效信号的协议(基本上仍然归结为超时)。
编辑补充:在应用层协议中实现"are you there"消息可以提供一种方法来请求对等方的响应,以便能够测量超时and/or 在连接空闲时检测连接关闭。由于这或多或少相当于本地计算机从远程对等点请求心跳的一种方式,它与您已有的类似。
另一方面,它确实提供了一个框架,在该框架中,本地计算机可以在不干扰应用程序的情况下尝试向对等方发送未经请求的消息。这样,如果 TCP 实现已将连接标记为关闭,无论是因为 TCP 级超时还是因为另一端关闭它,那么本地机器将在那时收到关闭通知。
无论阻塞模式如何,如果对等方因任何原因断开连接,一系列 TCP send()
操作最终将失败并显示 ECONNRESET
,并且 TCP recv()
将 return 如果对等点完全断开连接则为零。
我一直在玩弄 C 语言中的基本 client/server 通信,我正在尝试确定检测断开连接的客户端的最佳方法。我知道如果我想要一个阻塞解决方案,我可以简单地从 read() 分支出来。但是,在非阻塞上下文中,尤其是在网络中断而不是完全断开连接的情况下,read() 是否仍会及时检测到断开的连接?
现在我只是定期从客户端发送保持活动消息并检查服务器端超时,我想知道是否有更简洁的方法。
一般来说,您无法肯定地检测到未完全断开连接的客户端。
编辑:也就是说,没有通用的 are_you_still_there()
功能,也没有办法实现您可以始终依赖的快速交付功能 "no"既没有假阴性也没有假阳性的反应。
如果您使用的是无连接网络协议(即 UDP),那么您根本无法肯定地检测到客户端已永久消失。
编辑:TCP 在接收方未确认接收的情况下提供自动数据重传。相同数据的多次重新传输是可能的,在这种情况下,(重新)传输之间的超时会呈指数增长。在没有确认的情况下达到重传阈值次数或重传超时阈值后,TCP 子系统将认为连接断开,但这可能需要几分钟甚至几十分钟,具体取决于本地协议实现和参数。
如果 TCP 实现检测到连接中断,您可以依靠 read()
发出错误信号,无论是超时还是远程对等点强行切断连接。但是,如果您的 "timely" 概念与 TCP 实现的概念大不相同,则确保以 "timely" 方式将此类错误传递给应用程序可能很棘手或不可能。
人们通常通过使用 [edit: application-level] 超时来判断何时释放专用于服务客户端的资源,或者可能通过更高级别的资源来处理这个问题提供心跳信号或等效信号的协议(基本上仍然归结为超时)。
编辑补充:在应用层协议中实现"are you there"消息可以提供一种方法来请求对等方的响应,以便能够测量超时and/or 在连接空闲时检测连接关闭。由于这或多或少相当于本地计算机从远程对等点请求心跳的一种方式,它与您已有的类似。
另一方面,它确实提供了一个框架,在该框架中,本地计算机可以在不干扰应用程序的情况下尝试向对等方发送未经请求的消息。这样,如果 TCP 实现已将连接标记为关闭,无论是因为 TCP 级超时还是因为另一端关闭它,那么本地机器将在那时收到关闭通知。
无论阻塞模式如何,如果对等方因任何原因断开连接,一系列 TCP send()
操作最终将失败并显示 ECONNRESET
,并且 TCP recv()
将 return 如果对等点完全断开连接则为零。