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

Art*_*yom 4 linux epoll tcp keep-alive

我使用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)
Run Code Online (Sandbox Code Playgroud)

Epoll等待在套接字上使用EPOLLIN | EPOLLHUP退出而没有问题.

但是,如果我尝试向socket写入很多东西,直到我得到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!!!
Run Code Online (Sandbox Code Playgroud)
  • 怎么解决这个问题?
  • 有没有人见过类似的问题?
  • 任何可能的方向?

编辑:附加信息

当我监控与wireshark的通信时,在第一种情况下(读取)我会在几秒钟内得到一次ack请求.但在第二种情况下,我根本检测不到.

Old*_*Pro 12

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

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

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