一尘不染

在写入阻止的套接字上使用TCP Keep-Alive获取断开连接通知

linux

我使用TCP Keep-Alive选项来检测死连接。它与使用读取套接字的连接一起工作良好:

setsockopt(mysock,...) // set various keep alive options

epoll_ctl(ep,mysock,{EPOLLIN|EPOLERR|EPOLLHUP},)
epoll_wait -> (exits after several seconds when remove host disconnects cable)

Epoll等待通过套接字上的EPOLLIN | EPOLLHUP退出而没有问题。

但是,如果我尝试向套接字写很多东西,直到得到EAGAIN,然后轮询读写,则在断开电缆连接时不会出现错误:

setsockopt(mysock,...) // set various keep alive options

while(send() != EAGAIN)
   ;
epoll_ctl(ep,mysock,{EPOLLIN|EPOLLOUT|EPOLERR|EPOLLHUP},)
epoll_wait -> --- Never exits!!!! even when the cable of the remove host is disconnected!!!
  • 如何解决呢?
  • 有人看到过类似的问题吗?
  • 有什么可能的方向吗?

编辑: 附加信息

当我使用wireshark监视通信时,在第一种情况下(阅读中),我每隔几秒钟收到一次确认请求。但是在第二种情况下,我根本没有检测到它们。


阅读 324

收藏
2020-06-03

共1个答案

一尘不染

如果在传输所有数据之前拔出网络连接,则该连接不会空闲,因此在某些实现中,保持活动计时器不会启动。(请记住,keepalive不是TCP规范的一部分,因此它的实现方式根本不一致。)通常,由于指数补偿和大量重试(tcp_retries2默认为15)的组合,它可能会占用在Keepalive计时器启动之前,传输需要30分钟才能重试超时。

解决方法(如果有)取决于您所使用的特定TCP实现。一些较新版本的Linux(2011年1月4日发布的内核版本2.6.37)实现了TCP_USER_TIMEOUT。

通常的建议是在应用程序级别实现通信超时,而不是始终使用基于TCP的keepalive。参见例如HTTP Keep-
Alive

2020-06-03