目录

1 TCP保活的必要性

2 导致TCP断连的因素

3 保活的两种方式

3.1 应用层面的心跳机制

3.2 TCP协议自带的保活功能

4 两种方式的优劣性

5 到底选用那种心跳方式?

6 配置 Keep-alive

6.1 socket 进行单独设定keepalive(代码层面)

6.2 修改系统配置文件

7 测试结果


1 TCP保活的必要性

  1. 多防火墙等对于空闲socket自动关闭
  2. 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制.

2 导致TCP断连的因素

如果网络正常, socket也通过close操作来进行优雅的关闭, 那么一切完美. 可是有很多情况, 比如网线故障, 客户端一侧突然断电或者崩溃等等, 这些情况server并不能正常检测到连接的断开.

3 保活的两种方式

3.1 应用层面的心跳机制

自定义心跳消息头. 一般客户端主动发送, 服务器接收后进行回应(也可以不回应). 这里不进行详述.

PS: 有人从软件的功能角度列出第三种方式, 就是通过第三方软件来进行探测, 确定连接的有效性. 这种方式局限性很大, 而且不属于软件内部的功能实现. 不进行讨论.

3.2 TCP协议自带的保活功能

打开keep-alive功能即可. 具体属性也可以通过API设定.

4 两种方式的优劣性

TCP协议自带的保活功能, 使用起来简单, 减少了应用层代码的复杂度. 推测也会更节省流量, 因为一般来说应用层的数据传输到协议层时都会被加上额外的包头包尾. 由TCP协议提供的检活, 其发的探测包, 理论上实现的会更精妙(用更少的字节完成更多的目标), 耗费更少的流量.

由应用自己实现的应用层的心跳, 为心跳消息额外定义一个消息类型就可以了. 就是应用正常的消息包, 只是这个包特殊点, 专门用来检活而已, 通常比较小, 可能只有消息头就可以了, 除非需要额外的信息.

应用层心跳的好处我个人的理解有两点:

一是比较灵活, 因为协议层的心跳只能提供最纯粹的检活功能, 但是应用层自己可以随意控制, 包括协议可能提供的是秒级的, 但是你想做成毫秒级的都任意(虽然实际几乎不会有这种时间级别的心跳), 包里还甚至可以携带额外的信息, 这些都是灵活之处.

二是通用, 应用层的心跳不依赖协议. 如果有一天不用TCP要改为UDP了, 协议层不提供心跳机制了, 但是你应用层的心跳依旧是通用的, 可能只需要做少许改动就可以继续使用.

应用层心跳的不好的地方也很显而易见, 增加开发工作量, 由于应用特定的网络框架, 还可能很增加代码结构的复杂度. 再就是根据上面的推测, 应用层心跳的流量消耗还是更大的, 毕竟这本质上还是个普通的数据包.

5 到底选用那种心跳方式?

优劣点第4节已经进行了阐述, 因此如果能确定你们更换协议的可能性非常小, 同时只是需要检活的功能, 那么用协议自带的就绝对OK了, 使用简单而且高效. 有些自负的人总喜欢用自己搞的, 来代替成熟协议自带的东西, 代替系统内核提供的东西, 其实往往你应用层实现的东西, 都是更拙劣的. 网上看了一些关于协议的Keep-alive不靠谱的说法, 也都比较空想和想当然, 都没有拿出任何事实论据或实验数据. 这点大家有见解, 欢迎交流哈~

6 配置 Keep-alive

keepalive默认是关闭的, 因为虽然流量极小, 毕竟是开销. 因此需要用户手动开启. 有两种方式开启.

6.1 socket 进行单独设定keepalive(代码层面)

#include <netinet/tcp.h> //for SOL_TCP和TCP_KEEPIDLE等宏
int socket_set_keepalive( int fd)
{int alive, idle, cnt, intv;/* Set: use keepalive on fd *///缺省值:0(关闭),之前忘了开了,始终未看到现象alive = 1;if (setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &alive, sizeof alive) != 0){printf ("Set keepalive error: %s.\n" , strerror (errno));return -1;}/* 10秒钟无数据,触发保活机制,发送保活包 */idle = 10;if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE , &idle, sizeof idle) != 0){printf ("Set keepalive idle error: %s.\n" , strerror (errno));return -1;}/* 如果没有收到回应,则3秒钟后重发保活包 */intv = 3;if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL , &intv, sizeof intv) != 0){printf ("Set keepalive intv error: %s.\n", strerror (errno));return -1;}/* 连续5次没收到保活包,视为连接失效,此时本端会发送RST关闭连接 */cnt = 5;if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT , &cnt, sizeof cnt) != 0){printf ("Set keepalive cnt error: %s.\n", strerror (errno));return -1;}return 0;
}

6.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 10 > /proc/sys/net/ipv4/tcp_keepalive_time
#echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
#echo 3 > /proc/sys/net/ipv4/tcp_keepalive_intvl  

7 测试结果

  1. 客户端调用 socket_set_keepalive()接口配置keepalive参数,并使能keepalive
  2. 客户端建链完成之后向服务器发送一包数据后睡眠
  3. 服务器收包客户端端的一包数据之后也进入睡眠,此时通信双方再也没有数据传输
  4. 客户端keepalvie超时开始发送心跳包,收到服务器响应,每隔tcp_keepalive_time时长发送一次
  5. 配置防火墙丢掉客户端的报文后,客户端开始每隔tcp_keepalive_intvl时长发送一次,发送tcp_keepalive_probes次
  6. 在tcp_keepalive_probes次数均无响应之后,客户端发送RST报文关闭连接

服务器配置防火墙,丢掉客户端过来的报文

[root@localhost wq]# iptables -t filter -A INPUT -s 10.228.90.11/32 -p tcp --sport 8002 -j DROP

linux内核协议栈 TCP连接探测中的Keepalive和心跳包使用相关推荐

  1. TCP连接探测中的Keepalive和心跳包

    1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...

  2. TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活

    1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...

  3. linux内核协议栈 TCP数据发送之发送窗口

    目录 1 发送窗口概述 2 snd_una 和 snd_wnd 的更新 2.1 发送窗口初始化 2.1.1 客户端初始化 2.1.2 服务器端初始化 2.2 本地接收窗口 rcv_wnd 通告 2.2 ...

  4. linux内核协议栈 TCP层数据发送之TSO/GSO

    目录 1 基本概念 2 TCP延迟分段判定 2.1 客户端初始化 2.2 服务器端初始化 2.3 sk_setup_caps() 3 整体结构 4. TCP发送路径TSO处理 4.1 tcp_send ...

  5. linux内核协议栈 TCP选项之MSS

    目录 1 MSS概述 2 客户端三次握手 2.1 发送SYN段MSS选项值 2.1.1 tcp_advertise_mss() 2.1.2 tp->advmss的初始化 2.2 接收SYN+AC ...

  6. linux内核协议栈 TCP选项之SACK选项概述

    目录 1 SACK概述 1.1 SACK允许选项 1.2 SACK选项 2 SACK允许选项的发送和接收 2.1 客户端 SYN 段发送 tcp_transmit_skb 2.1.1 syn包构造可选 ...

  7. linux内核协议栈 TCP层数据发送之发送新数

    目录 1 tcp_push() 2 __tcp_push_pending_frames() 2.1 sk_write_queue队列未发送数据推送 tcp_write_xmit() 2.1.1 拥塞窗 ...

  8. Linux 内核协议栈之TCP连接关闭

    Close行为: 当应用程序在调用close()函数关闭TCP连接时,Linux内核的默认行为是将套接口发送队列里的原有数据(比如之前残留的数据)以及新加入 的数据(比如函数close()产生的FIN ...

  9. 什么叫linux网络协议栈,我们为什么使用Linux内核的TCP协议栈

    最近的一篇文章提出了"我们为什么使用Linux内核的TCP协议栈"的问题,并在Hacker News引发了非常有意思的讨论. 在CloudFlare的时候我也曾思考这个问题.我的经 ...

最新文章

  1. weblogic学习笔记(1)
  2. 怎么知道python有哪些库、哪些方法-哪些 Python 库让你相见恨晚?
  3. 保25ms争10ms——Zenlayer如何保持出海业务的超低延时
  4. java机试_java机试要点
  5. [渝粤教育] 辽宁对外经贸学院 国际集装箱多式联运 参考 资料
  6. android程序获取WIFI的IP地址和MAC地址
  7. 两种贝塞尔曲线选点方法的对比
  8. 野生前端的数据结构基础练习(4)——字典
  9. springboot+aop切点记录请求和响应信息
  10. js获取图片原始大小
  11. 如何在 macOS 中批量重命名文件?
  12. mysql删完数据表空间没释放_mysql删除表后,空间一直不释放
  13. 获得每种调制方式中每个信噪比的准确度
  14. Nginx篇05-http长连接和keeplive
  15. 开关电源PFC电路原理详解及matlab仿真
  16. 正交试验设计例题及答案_正交试验设计与数理统计作业.doc
  17. 设置cookie存活时间_Cookie所有知识点
  18. 转载标明出处用英语_转载怎么注明出处
  19. 荣耀9igoogle模式_创建自己的简单iGoogle小工具
  20. css竖向箭头符号_「右箭头符号」html实现右箭头 - seo实验室

热门文章

  1. LINUX 文本命令
  2. Linux基本应用篇
  3. 54.UDP报文格式详解
  4. quatzy获取参数强转异常,devtools类加载机制问题
  5. 图像评估指标:PSNR
  6. java 数组升序排序_Java sort()数组排序升序详解
  7. 阿里巴巴中间件开源项目盘点(持续更新)
  8. 转发 Mac 键盘上的按键操作
  9. 原作者彤砸(诶嘿嘿《聊聊我的故事 | 带一只柚子上路》【转载】
  10. 平衡车直立PID调节总结