TCP/IP-SO_KEEPALIVE

心跳包的实现有两种方式:

方法1:应用层自己实现的心跳包 
由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时 向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线;同样,如果客户端在一定时间内没 有收到服务器的心跳包,则认为连接不可用。

方法2:TCP的KeepAlive保活机制
因为要考虑到一个服务器通常会连接多个客户端,因此由用户在应用层自己实现心跳包,代码较多 且稍显复杂,而利用TCP/IP协议层为内置的KeepAlive功能来实现心跳功能则简单得多。 不论是服务端还是客户端,一方开启KeepAlive功能后,就会自动在规定时间内向对方发送心跳包, 而另一方在收到心跳包后就会自动回复,以告诉对方我仍然在线。 因为开启KeepAlive功能需要消耗额外的宽带和流量,所以TCP协议层默认并不开启KeepAlive功 能,尽管这微不足道,但在按流量计费的环境下增加了费用,另一方面,KeepAlive设置不合理时可能会 因为短暂的网络波动而断开健康的TCP连接。并且,默认的KeepAlive超时需要7,200,000 MilliSeconds, 即2小时,探测次数为5次。对于很多服务端应用程序来说,2小时的空闲时间太长。因此,我们需要手工开启KeepAlive功能并设置合理的KeepAlive参数。
以上转自网络。

int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)

参数:  
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。

例如,

if(setsockopt(clientfd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) != 0)
{
        cloud_thread_e("set  SO_KEEPALIVE failed %d\r\n", errno);
}

 

SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。

设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:

1、对方接收一切正常:以期望的ACK响应,2小时后,TCP将发出另一个探测分节。

2、对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。

3、对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。

 

TCP中已有SO_KEEPALIVE选项,为什么还要在应用层加入心跳包机制??

SO_Keeplive是实现在服务器侧,客户端被动响应,缺省超时时间为120分钟,这是RFC协议标准规范。

SO_Keeplive是实现在TCP协议栈(四层),应用层的心跳实现在第七层,本质没有任何区别,但应用层需要自己来定义心跳包格式。

之所以实现在服务器侧,是因为与客户端相比,服务器侧的寿命更长,因为服务器侧需要不间断地提供服务,而客户端可能由于用户下班而合上电脑(TCP没有来得及发送FIN关闭连接),这样的话,服务器侧就会有很多不可用的TCP连接(established),这样的连接依然会占用服务器内存资源,于是就设计这个keepalive 来检测客户端是否可用,如果几次重传keepalive ,客户端没有相应,删除连接,释放资源。

需要指出的是,超时时间是指TCP连接没有任何数据、控制字传输的时间,如果有任何数据传输,会刷新定时器,重新走表。

TCP心跳是一个备受争议的实现,只是一个option,不是强制标准。

之所以应用层需要独立实现自己的心跳,是因为超时时间较长,无法给应用层提供快速的反馈。

所以类似BGP协议就独立实现了自己的keepalive,最小可以设置一秒钟,三次没有应答即可以Reset连接,最快三秒可以检测到失效。

而三秒依然太慢,可以用另外一个协议 BFD来提供更快发现链路失效,最快可以配置成10ms
,三次超时(30ms)就可以完成失效检测。

 

转载于:https://www.cnblogs.com/1119reya/p/10382276.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值