闲说HeartBeat心跳包和TCP协议的KeepAlive机制
很多应用层协议都有HeartBeat机制,通常是客户端每隔一小段时间向服务器发送一个数据包,通知服务器自己仍然在线,并传输一些可能必要的数据。使用心跳包的典型协议是IM,比如QQ/MSN/飞信等协议。
学过TCP/IP的同学应该都知道,传输层的两个主要协议是UDP和TCP,其中UDP是无连接的、面向packet的,而TCP协议是有连接、面向流的协议。
所以非常容易理解,使用UDP协议的客户端(例如早期的“OICQ”,听说OICQ.com这两天被抢注了来着,好古老的回忆)需要定时向服务器发送心跳包,告诉服务器自己在线。
然而,MSN和现在的QQ往往使用的是TCP连接了,尽管TCP/IP底层提供了可选的KeepAlive(ACK-ACK包)机制,但是它们也还是实现了更高层的心跳包。似乎既浪费流量又浪费CPU,有点莫名其妙。
具体查了下,TCP的KeepAlive机制是这样的,首先它貌似默认是不打开的,要用setsockopt将SOL_SOCKET.SO_KEEPALIVE设置为1才是打开,并且可以设置三个参数tcp_keepalive_time/tcp_keepalive_probes/tcp_keepalive_intvl,分别表示连接闲置多久开始发keepalive的ack包、发几个ack包不回复才当对方死了、两个ack包之间间隔多长,在我测试的Ubuntu Server 10.04下面默认值是7200秒(2个小时,要不要这么蛋疼啊!)、9次、75秒。于是连接就了有一个超时时间窗口,如果连接之间没有通信,这个时间窗口会逐渐减小,当它减小到零的时候,TCP协议会向对方发一个带有ACK标志的空数据包(KeepAlive探针),对方在收到ACK包以后,如果连接一切正常,应该回复一个ACK;如果连接出现错误了(例如对方重启了,连接状态丢失),则应当回复一个RST;如果对方没有回复,服务器每隔intvl的时间再发ACK,如果连续probes个包都被无视了,说明连接被断开了。
这里有一篇非常详细的介绍文章: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO ,包括了KeepAlive的介绍、相关内核参数、C编程接口、如何为现有应用(可以或者不可以修改源码的)启用KeepAlive机制,很值得详读。
这篇文章的2.4节说的是“Preventing disconnection due to network inactivity”,阻止因网络连接不活跃(长时间没有数据包)而导致的连接中断,说的是,很多网络设备,尤其是NAT路由器,由于其硬件的限制(例如内存、CPU处理能力),无法保持其上的所有连接,因此在必要的时候,会在连接池中选择一些不活跃的连接踢掉。典型做法是LRU,把最久没有数据的连接给T掉。通过使用TCP的KeepAlive机制(修改那个time参数),可以让连接每隔一小段时间就产生一些ack包,以降低被T掉的风险,当然,这样的代价是额外的网络和CPU负担。
前面说到,许多IM协议实现了自己的心跳机制,而不是直接依赖于底层的机制,不知道真正的原因是什么。
就我看来,一些简单的协议,直接使用底层机制就可以了,对上层完全透明,降低了开发难度,不用管理连接对应的状态。而那些自己实现心跳机制的协议,应该是期望通过发送心跳包的同时来传输一些数据,这样服务端可以获知更多的状态。例如某些客户端很喜欢收集用户的信息……反正是要发个包,不如再塞点数据,否则包头又浪费了……
大概就是这样吧,如果有大牛知道真正的原因,还望不吝赐教。
@2012-04-21
p.s. 通过咨询某个做过IM的同事,参考答案应该是,自己实现的心跳机制通用,可以无视底层的UDP或TCP协议。如果只是用TCP协议的话,那么直接使用KeepAlive机制就足够了。
@2015-09-14
补充一下 @Jack的回复:
“心跳除了说明应用程序还活着(进程还在,网络通畅),更重要的是表明应用程序还能正常工作。而 TCP keepalive 有操作系统负责探查,即便进程死锁,或阻塞,操作系统也会如常收发 TCP keepalive 消息。对方无法得知这一异常。摘自《Linux 多线程服务端编程》”
1.KeepAlive机制很多情况无法检测出来,如网络连接被软件禁用等,不够可靠,网络状态复杂的情况下这种情况尤其严重。2.自己实现心跳可以加入更灵活与实用的机制,比如少了一个心跳,可以马上再次检查,检查间隔递减,这样可以更快的感知网络状态,而不是等待固定的时间。
--
转载请注明出自 http://www.felix021.com/blog/read.php?2076 ,如是转载文则注明原出处,谢谢:)
闲说HeartBeat心跳包和TCP协议的KeepAlive机制的更多相关文章
- TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活
1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...
- tcpdump抓包二进制tcp协议详细分析
1.tcpdump -i eth0 port 11751 and src host 192.168.1.34 -x -s0 tcpdump: verbose output suppressed, us ...
- Wireshark抓包分析TCP协议
版权声明:本文为作者原创文章,可以随意转载,但必须在明确位置表明出处!!! 之前有一篇文章介绍了http协议「初识http协议」, http协议协议是基于tcp协议的,所以作者觉得有必要针对tcp ...
- scoket模块 粘包问题 tcp协议特点 重启服务器会遇到地址被占用问题
scoket()模块函数用法 import socket socket.socket(socket_family,socket_type,protocal=0) 获取tcp/ip套接字 tcpsock ...
- 聊聊 TCP 中的 KeepAlive 机制
KeepAlive并不是TCP协议规范的一部分,但在几乎所有的TCP/IP协议栈(不管是Linux还是Windows)中,都实现了KeepAlive功能 RFC1122#TCP Keep-Alives ...
- Tcp协议的keepalive功能
L:128
- 为什么心跳包(HeartBeat)是必须的?
几乎所有的网游服务端都有心跳包(HeartBeat或Ping)的设计,在最近开发手游服务端时,也用到了心跳包.思考思考,心跳包是必须的吗?为什么需要心跳包?TCP没有提供断线检测的方法吗?TCP提供的 ...
- 心跳包(HeartBeat)
http://itindex.net/detail/52922-%E5%BF%83%E8%B7%B3-heartbeat-coderzh 几乎所有的网游服务端都有心跳包(HeartBeat或Ping) ...
- TCP连接探测中的Keepalive 和心跳包
采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...
随机推荐
- 打造自己的php动态连接库文件
http://blog.163.com/weibin_li/blog/static/1901464172012325115517181/
- 破解加密PDF文件pdfcrack
破解加密PDF文件pdfcrack PDF是常见的文档格式.它允许用户设置双重密码来保护文档.第一重是用户密码(user password),当打开PDF文档,输入该密码.第二重是所有者密码(ow ...
- 浏览器控制台console
console对象 console对象代表浏览器的JavaScript控制台.虽然它还不是标准,但是各大浏览器都原生支持,已经成为事实上的标准. console对象主要有两个作用: 显示网页代码运行时 ...
- 安装dede显示dir的解决办法
1.遇见安装页面出现dir 2.你这个肯定是已经安装过了的程序,把install文件夹下的index.html删掉,,你再看看install文件夹下有没有install_lock.txt 和index ...
- [转]webpack进阶构建项目(一)
阅读目录 1.理解webpack加载器 2.html-webpack-plugin学习 3.压缩js与css 4.理解less-loader加载器的使用 5.理解babel-loader加载器 6.理 ...
- Redis的PHP操作手册(转)
String 类型操作 string是redis最基本的类型,而且string类型是二进制安全的.意思是redis的string可以包含任何数据.比如jpg图片或者序列化的对象 $redis-> ...
- Winform TextBox中只能输入数字的几种常用方法(C#)
方法一: private void tBox_KeyPress(object sender, KeyPressEventArgs e) { ; //禁止空格键 )) return; //处理负数 if ...
- java实现图像灰度化
/*在研究Java实现将一张图片转成字符画的时候,发现将图像转化字符串是根据照片的灰度采用不同的字符画出来,形成一个灰度表.于是就研究了下关于灰度值这个东西,于是跳了一个大坑...因为鄙人用的ubun ...
- centos7 最小化安装没有ifconfig及修改网卡名enoxxx为ethX
问题: 1.最小化安装centos7后发现无ifconfig命令 想通过ifconfig查看ip地址发现ifconfig命令不存在,可通过命令 #ip addr //查看ip 或者 解决: ...
- Strom的配置安装
1.准备环境 1.1配置列表 配置项 版本信息 OS Red Hat Enterprise Linux Server release 5.5 (Tikanga) IP 192.168.1.191/ ...