我是靠谱客的博主 闪闪香氛,最近开发中收集的这篇文章主要介绍TCP keep alive,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1  tcp keep alive 的作用

Socket 网络编程中,recv send 等函数通常都是阻塞的(默认),可能经常会遇到因连接关闭或网络等原因导致的send 或recv阻塞,占用系统资源,进而导致系统异常(卡住)。如果要避免这种问题,就要用到keep alive了。

首先了解因连接关闭导致的send等阻塞的情况:

对于一个正常的TCP连接,当我们用以阻塞方式调用recv或send的时候,如果此时TCP连接被对方正常关闭,即对方正确地调用了closesocket(或shutdown),我们调用的recv或send调用就能马上返回(报错,返回socket错误码)。这是因为closesocket(s)或者shutdown(s)会进行正常的关闭过程,会通知对方:TCP连接已经关闭,你不需要再发送或者接受消息了。但是,如果是因为网线突然被拔掉,TCP连接的任何一端的设备突然被断电或重启,则此时正在执行recv或send操作的一方就会因为没有任何连接中断的通知而一直等待下去,也就是系统会被长时间卡住。特别是对于某些小型的嵌入式系统,tcp tx buffer和rxbuffer可能处于一个内存区域,如果多个客户端中有一路tcp连接出现上述情况,就会影响到所有的tcp连接(这一路tcp连接send失败,会不断的尝试send,导致系统资源等被占用;或者recv失败,一直等待recv)。要解决上面的问题,主要是要让系统(tcp协议栈)或应用层知道链接已存在异常,不要再对该链接执行send或recv操作。

2 实现tcp keep alive

2.1 应用层自主实现

即我们自己在应用程序中编写心跳包程序,通常是定时向连接对端发送数据包,查看是否收到对端的ACK,如果有则认为连接正常,没有的话则本端主动断开连接。实现上并不复杂。

2.2 TCP协议栈自带keepAlive机制

TCP 协议栈自带的keepalive,原理上就是TCP内嵌的一个心跳包机制,通常默认是关闭的。简单讲就是,连接的一端(以服务器端举例)检测到超过一定时间(称为空闲时间,系统默认是 7200000 ms,即2个小时)没有数据传输,就会向client端发送一个keep-alive packet(该心跳包是ACK和当前TCP序列号减一的组合),如果收到client的响应,则重置计时器(即2小时重新计时),否则会每隔一定时间(通常默认是75s),重复尝试发送心跳包(通常默认是9次),如果一直没有收到client的响应,则终止此链接(release掉占用的资源)。

所以,当服务器端发送了心跳包时,此时client端情况为:

1. 仍然存在,且网络连接状况良好。此时client端立即返回一个ACK,server端接收到ACK后重置计时器。如2小时内该连接上有数据传输,那么在该时间上再向后推延2个小时。

2. 客户端异常关闭(网络断开,设备断电等)。这种情况下client端都不会响应。服务器没有收到对其发出心跳的响应,会按照预先的或默认的设置,在一定时间后重复发送keep-alive packet,并且重复发送一定次数。

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

2.3 使用TCP 内嵌的keep alive

  对于多数应用程序来说,TCP内嵌的keepalive 机制(通常)默认是关闭的,而且默认的相关参数,不太合理;例如2小时的空闲时间就太长了。因此往往需要在应用程序中开启Keepalive功能并设置合理的Keepalive参数。大多数的系统,都可以针对单独的socket来设置,也有少数系统不支持单独socket设置,对于这些系统,如果设置,那么影响是整个系统的所有socket链接。

通过setsockopt来打开keep alive,并设置keepalive参数:

 setsockopt(s,SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle)); 

setsockopt(s, SOL_TCP, TCP_KEEPINTVL,(void*)&keepInterval, sizeof(keepInterval)); 

setsockopt(s, SOL_TCP, TCP_KEEPCNT,(void*)&keepCount, sizeof(keepCount)); 

3 两种方式的优劣

应用层实现心跳的优点:

灵活且不依赖协议,而且重要是表明应用程序正常运行;缺点是增加额外的消耗。

TCP 自带的keep alive:

TCP协议自带的保活功能, 使用简单, 减少了应用层代码的复杂度,更节省流量。

 

最后

以上就是闪闪香氛为你收集整理的TCP keep alive的全部内容,希望文章能够帮你解决TCP keep alive所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部