Socket keepalive相关问题

【问题描述】

 CTRL-VM为TCP Server(192.168.0.1),BRAS-VM 97为TCP Client1(192.168.0.66),BRAS-VM 99为TCP Client 2(192.168.0.67)。

当BRAS-VM 97和BRAS-VM 99与CTRL-VM分别建立TCP连接后,分别将BRAS-VM 97和BRAS-VM 99关闭电源,从CTRL-VM查看BRAS-VM 97的TCP连接断开,BRAS-VM 99的TCP连接仍然存在,二者现象不一致

 

【问题定位】

到宿主机上进行抓包 tcpdump -i vnet5 -w vnet5.pcap

抓包如下

 

 

查看30012端口(server和client通信端口)报文,与66的连接是通过保活报文断开的,与67没有。初步怀疑是与66的连接设置了keep-alive,与67的没有设置?

 

【代码排查】

TCP Server端代码编写错误,将listenfd设置了keepalive,而不是acceptfd设置keepalive

 

 

【疑问1】

现象并不是必现的,原因是什么?

答:TCP不感知链路断开,除非报文发送过程中断连或者正好发生保活探测,或者受到对端FIN报文。也就是说即使没有设置keppalive也有概率会响应断连

【疑问2】

TCP Server端代码是一致的,未区分与client的连接。为什么有的时候是66的连接没断开,有的时候是67的?

答:

1)有一个client能设置keepalive的原因:给listen fd设置Keepalive上,后续acceptfd是可以继承Keepalive属性的

2)有一个client未设置keepalive的原因:第一个accpetfd是在给listen fd设置Keepalive之前,不会继承Keepalive属性

经验证,若有多个Client,也只会有第一个Client不会设置keepalive属性,其余的Client都可以继承Keepalive属性。

【总结】

查阅了一些资料得知

keepalive设置是socket相关的。
另外这些属性是sockt继承的,即listen的套接字设置该属性后,后面建立连接后的accept 套接字同样继承该属性(心跳属性)。

正常情况下,连接的另一端主动调用colse关闭连接,tcp会通知,我们知道了该连接已经关闭。但是如果tcp连接的另一端突然掉线,或者重启断电,这个时候我们并不知道网络已经关闭。而此时,如果有发送数据失败,tcp会自动进行重传。重传包的优先级高于keepalive,那就意味着,我们的keepalive总是不能发送出去。 而此时,我们也并不知道该连接已经出错而中断。在较长时间的重传失败之后,我们才会知道。所以应用层有时候会使用心跳包。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值