1. TCP保活的必要性服务器
1) 不少防火墙等对于空闲socket自动关闭网络
2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制.框架
2. 致使TCP断连的因素socket
若是网络正常, socket也经过close操做来进行优雅的关闭, 那么一切完美. 但是有不少状况, 好比网线故障, 客户端一侧忽然断电或者崩溃等等, 这些状况server并不能正常检测到链接的断开. tcp
3. 保活的两种方式:ide
1) 应用层面的心跳机制spa
自定义心跳消息头. 通常客户端主动发送, 服务器接收后进行回应(也能够不回应). 这里不进行详述..net
PS: 有人从软件的功能角度列出第三种方式, 就是经过第三方软件来进行探测, 肯定链接的有效性. 这种方式局限性很大, 并且不属于软件内部的功能实现. 不进行讨论.code
2) TCP协议自带的保活功能server
打开keep-alive功能便可. 具体属性也能够经过API设定.
4. 两种方式的优劣性
TCP协议自带的保活功能, 使用起来简单, 减小了应用层代码的复杂度. 推测也会更节省流量, 由于通常来讲应用层的数据传输到协议层时都会被加上额外的包头包尾. 由TCP协议提供的检活, 其发的探测包, 理论上实现的会更精妙(用更少的字节完成更多的目标), 耗费更少的流量.
由应用本身实现的应用层的心跳, 为心跳消息额外定义一个消息类型就能够了. 就是应用正常的消息包, 只是这个包特殊点, 专门用来检活而已, 一般比较小, 可能只有消息头就能够了, 除非须要额外的信息.
应用层心跳的好处我我的的理解有两点:
一是比较灵活, 由于协议层的心跳只能提供最纯粹的检活功能, 可是应用层本身能够随意控制, 包括协议可能提供的是秒级的, 可是你想作成毫秒级的都任意(虽然实际几乎不会有这种时间级别的心跳), 包里还甚至能够携带额外的信息, 这些都是灵活之处.
二是通用, 应用层的心跳不依赖协议. 若是有一天不用TCP要改成UDP了, 协议层不提供心跳机制了, 可是你应用层的心跳依旧是通用的, 可能只须要作少量改动就能够继续使用.
应用层心跳的很差的地方也很显而易见, 增长开发工做量, 因为应用特定的网络框架, 还可能很增长代码结构的复杂度. 再就是根据上面的推测, 应用层心跳的流量消耗仍是更大的, 毕竟这本质上仍是个普通的数据包.
5. 到底选用那种心跳方式?
优劣点第4节已经进行了阐述, 所以若是能肯定大家更换协议的可能性很是小, 同时只是须要检活的功能, 那么用协议自带的就绝对OK了, 使用简单并且高效. 有些自负的人总喜欢用本身搞的, 来代替成熟协议自带的东西, 代替系统内核提供的东西, 其实每每你应用层实现的东西, 都是更拙劣的. 网上看了一些关于协议的Keep-alive不靠谱的说法, 也都比较空想和想固然, 都没有拿出任何事实论据或实验数据. 这点你们有看法, 欢迎交流哈~
6. 类Unix平台如何使用Keep-alive
keepalive默认是关闭的, 由于虽然流量极小, 毕竟是开销. 所以须要用户手动开启. 有两种方式开启.
1) 在代码里针对每一个socket进行单独设定, 使用起来灵活.
除了keepAlive 开关, 还有keepIdle, keepInterval, keepCount 3个属性, 使用简单, 以下:
[cpp] view plaincopy
int keepAlive = 1; // 开启keepalive属性. 缺省值: 0(关闭)
int keepIdle = 60; // 若是在60秒内没有任何数据交互,则进行探测. 缺省值:7200(s)
int keepInterval = 5; // 探测时发探测包的时间间隔为5秒. 缺省值:75(s)
int keepCount = 2; // 探测重试的次数. 所有超时则认定链接失效..缺省值:9(次)
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(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));
使用时须要#include <netinet/tcp.h>, 不然SOL_TCP和TCP_KEEPIDLE等3个宏找不到.
ps: 忍不住吐槽一下, 网上大量绝不负责的转载, 千篇一概的搜索结果, 不少人根本都没进行过任何验证吧. 为了找这么个头文件都费了不小的事. 大多数帖子里的说的都是不可用的.
2) 修改配置文件, 对整个系统全部的socket有效.
咱们能够用cat命令查看到系统中这几个默认的值.
#cat /proc/sys/net/ipv4/tcp_keepalive_time 7200
#cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75
#cat /proc/sys/net/ipv4/tcp_keepalive_probes 9
修改它们:
#echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time
#echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl
#echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes