TCP之keepalive机制的应用场景

如果TCP连接被对方正常关闭,也就是说,对方是正确地调用了close或者shutdown的话,那么Recv或Send调用就能马上返回,并且报错。这是由于close或者shutdown有个正常的关闭过程,会告诉对方“TCP连接已经关闭,你不需要再发送或者接受消息了”。

但是,如果连接被意外断开,客户端并没有正常关闭socket。双方并未按照协议上的四次挥手去断开连接。那么这时候正在执行Recv或Send操作的一方就会因为没有任何连接中断的通知而一直等待下去,也就是会被长时间卡住。像这种如果一方已经关闭或异常终止连接,而另一方却不知道,我们将这样的TCP连接称为半打开的。

 

解决意外中断办法都是利用保活机制。而保活机制分又可以让底层实现也可自己实现。

一种是应用层的心跳机制;

还有一种就是启用TCP的keepAlive机制;

 

以服务器端为例,如果当前server端检测到超过一定时间没有数据传输,那么会向client端发送一个keep-alive packet(该keep-alive packet就是ACK和当前TCP序列号减一的组合),此时client端应该为以下三种情况之一:

1. client端仍然存在,网络连接状况良好。此时client端会返回一个ACK。server端接收到ACK后重置计时器(复位存活定时器),在一定时间后再发送探测。如果连接上一直有数据传输,那么在该时间基础上向后推延一段时间。

2. 客户端异常关闭,或是网络断开。在这两种情况下,client端都不会响应。服务器没有收到对其发出探测的响应,并且在一定时间(系统默认为1000 ms)后重复发送keep-alive packet,并且重复发送一定次数。

3. 客户端曾经崩溃,但已经重启。这种情况下,服务器将会收到对其存活探测的响应,但该响应是一个复位(RST),从而引起服务器对连接的终止。

 

在应用层socket编程的表现为:当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ACK的响应包),select/epoll会返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT。

 

范例:

  1.  int keepAlive = 1; // 开启keepalive属性  
  2.  int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测   
  3.  int keepInterval = 5; // 探测时发包的时间间隔为5 秒  
  4.  int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.  
  5.   
  6.  setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));  
  7.  setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));  
  8.  setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));  
  9.  setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));   

转载于:https://my.oschina.net/u/2940064/blog/1506309

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值