当前位置:  开发笔记 > 编程语言 > 正文

检测TCP客户端断开连接

如何解决《检测TCP客户端断开连接》经验,为你挑选了2个好方法。

假设我正在运行一个简单的服务器并且已经accept()从客户端编辑了一个连接.

告诉客户端何时断开连接的最佳方式是什么?通常情况下,客户端应该发送一个关闭命令,但如果它手动断开连接或完全失去网络连接怎么办?服务器如何检测或处理此问题?



1> user207421..:

在TCP中,只有一种方法可以检测到有序断开,即从read()/recv()/recvXXX()读取时获取零作为返回值.

还有一种可靠的方法来检测断开的连接:写入它.在对断开的连接进行足够的写入之后,TCP将进行足够的重试和超时,以确定它已损坏并最终导致write()/send()/sendXXX()返回-1,其errno/WSAGetLastError()值为ECONNRESET,或在某些情况下"连接超时".请注意,后者与"连接超时"不同,后者可能出现在连接阶段.

您还应设置合理的读取超时,并删除失败的连接.

这里的答案是关于ioctl()FIONREAD无意义的竞争.所有这一切都告诉您当前在套接字接收缓冲区中有多少字节,可以无阻塞地读取.如果客户端没有向您发送任何不构成断开连接的五分钟内的任何内容,但它确实会导致FIONREAD零.不一样的是:甚至没有关闭.


@EJP我已多次说过,如果应用程序正在等待select/epoll/kevent准备好读取,那么它将被警告进行读取以获取错误.你一直对此提出异议,一再坚持要做更多的写作.你没有说过读取,并且对于epoll,事实上,不需要读取或写入,因为epoll可以直接发出超时信号.可能也很关键.
@Jay问题是关于如何检测TCP断开连接,而不是关于导致连接重置的原因."连接重置"有很多原因,我不同意它们中的任何一个构成"正常操作".根据定义,这是一种异常情况.
@ user1055568单个写入通常只是缓冲并通过网络异步发送,除非它非常大.您需要发出足够的写入,以便在原始写入时所有内部计时器和重试都已用尽,以便检测到错误.
如果应用程序不继续发出写入,则无法保证在连接中断后它将发出任何写入.虽然在连接失败后发出的一次写入就足够了,但连接可能随时失败,如果您无限期地停止写入,则在连接失败后您无法知道是否发出了一次写入.
@ user1055568如果您只进行读取操作,则表示您没有对网络执行任何操作,因此除非对等方有足够的权限进行重置,否则您不会遇到任何错误情况.如果你写,你正在为网络做事,所以如果有的话,你最终会遇到错误的情况.
@EJP你在胡说八道.在单次写入内部超时后执行单次读取就足以获取错误.如果您正在等待带有select/epoll/kqueue的I/O事件,则会在发生这种情况时收到警报.

2> 小智..:

为了进一步扩展这一点:

如果您正在运行服务器,则需要使用TCP_KEEPALIVE来监视客户端连接,或者自己执行类似的操作,或者了解通过连接运行的数据/协议.

基本上,如果连接被杀死(即没有正确关闭),那么服务器在尝试向客户端写入内容之前不会注意到,这就是keepalive为您实现的.或者,如果您更好地了解协议,则无论如何都可以断开不活动超时.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有