什么是TCP心跳机制
很多应用层协(xie)议都有HeartBeat机(ji)制,通常是客户端每隔一小段时间向服(fu)务器(qi)发送一个数据包,通知服(fu)务器(qi)自(zi)己(ji)仍(reng)然在线,并(bing)传输一些(xie)可(ke)能必要的(de)数据。使用心跳包的(de)典型协(xie)议是IM,比如QQ/MSN/飞信等(deng)协(xie)议。
心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心(xin)跳(tiao)包一(yi)般来(lai)说都是在(zai)逻辑层发送(song)空(kong)的(de)(de)echo包来(lai)实现的(de)(de)。下一(yi)个定(ding)时器(qi),在(zai)一(yi)定(ding)时间间隔(ge)下发送(song)一(yi)个空(kong)包给客户(hu)(hu)端(duan),然(ran)后(hou)客户(hu)(hu)端(duan)反馈(kui)一(yi)个同(tong)样的(de)(de)空(kong)包回(hui)来(lai),服务器(qi)如果(guo)在(zai)一(yi)定(ding)时间内收不到客户(hu)(hu)端(duan)发送(song)过来(lai)的(de)(de)反馈(kui)包,那(nei)就只(zhi)有认(ren)定(ding)说掉线了。
其实,要判定(ding)掉线(xian),只需(xu)要send或者recv一(yi)(yi)下(xia),如果结果为零,则(ze)为掉线(xian)。但(dan)是(shi)(shi),在长连(lian)(lian)接下(xia),有(you)可能(neng)很(hen)长一(yi)(yi)段时间(jian)都(dou)没有(you)数据(ju)(ju)往来。理论上说,这(zhei)个(ge)连(lian)(lian)接是(shi)(shi)一(yi)(yi)直(zhi)保持连(lian)(lian)接的(de),但(dan)是(shi)(shi)实际情况中,如果中间(jian)节点出(chu)现什么故障是(shi)(shi)难以知(zhi)道的(de)。更要命的(de)是(shi)(shi),有(you)的(de)节点(防火墙)会自动把一(yi)(yi)定(ding)时间(jian)之内没有(you)数据(ju)(ju)交(jiao)互的(de)连(lian)(lian)接给(ji)断掉。在这(zhei)个(ge)时候,就需(xu)要我们的(de)心跳(tiao)包了,用于(yu)维持长连(lian)(lian)接,保活(huo)。
在获(huo)知了(le)断(duan)线之后,服务器逻辑可能需(xu)要做(zuo)一些事情,比(bi)如断(duan)线后的(de)数据清理呀,重新连接呀……当然,这个自然是(shi)要由逻辑层根据需(xu)求去做(zuo)了(le)。
总的来说(shuo),心跳包主要(yao)(yao)也(ye)就是用于长连(lian)接(jie)的保(bao)活和断线(xian)处理。一般(ban)的应用下,判定时(shi)间在30-40秒比较不错。如(ru)果实在要(yao)(yao)求(qiu)高,那就在6-9秒。
心跳包的发送,通常有两种技术
方法1:应用层自己实现的心跳包
由应用程序(xu)自己发送心跳包来检测连接是(shi)否正常,大致的方法是(shi):服务(wu)(wu)器在一(yi)个(ge) Timer事件中定时(shi) 向客(ke)(ke)(ke)户(hu)(hu)端(duan)发送一(yi)个(ge)短小精悍的数据包,然(ran)后(hou)启动一(yi)个(ge)低级别(bie)的线(xian)程,在该线(xian)程中不(bu)断检测客(ke)(ke)(ke)户(hu)(hu)端(duan)的回应, 如果(guo)在一(yi)定时(shi)间内没有收(shou)到客(ke)(ke)(ke)户(hu)(hu)端(duan)的回应,即认(ren)为客(ke)(ke)(ke)户(hu)(hu)端(duan)已(yi)经掉线(xian);同样,如果(guo)客(ke)(ke)(ke)户(hu)(hu)端(duan)在一(yi)定时(shi)间内没 有收(shou)到服务(wu)(wu)器的心跳包,则认(ren)为连接不(bu)可用。
方法2:TCP的KeepAlive保活机制
因为(wei)要考虑到(dao)(dao)一个服(fu)务器(qi)通常会(hui)连接多(duo)(duo)个客(ke)户端(duan)(duan),因此由用(yong)(yong)(yong)户在(zai)应用(yong)(yong)(yong)层(ceng)自(zi)己实现心(xin)跳(tiao)包(bao),代(dai)码(ma)较多(duo)(duo) 且(qie)稍显复(fu)杂,而利用(yong)(yong)(yong)TCP/IP协议层(ceng)为(wei)内(nei)置(zhi)的(de)(de)(de)(de)KeepAlive功能(neng)来(lai)实现心(xin)跳(tiao)功能(neng)则简单得多(duo)(duo)。 不(bu)论(lun)是服(fu)务端(duan)(duan)还是客(ke)户端(duan)(duan),一方(fang)(fang)开(kai)启(qi)(qi)KeepAlive功能(neng)后,就会(hui)自(zi)动(dong)(dong)在(zai)规(gui)定时间内(nei)向对方(fang)(fang)发送(song)心(xin)跳(tiao)包(bao), 而另(ling)一方(fang)(fang)在(zai)收到(dao)(dao)心(xin)跳(tiao)包(bao)后就会(hui)自(zi)动(dong)(dong)回(hui)复(fu),以告(gao)诉对方(fang)(fang)我(wo)仍然在(zai)线。 因为(wei)开(kai)启(qi)(qi)KeepAlive功能(neng)需要消耗额外的(de)(de)(de)(de)宽(kuan)带(dai)和(he)流量(liang),所以TCP协议层(ceng)默认并不(bu)开(kai)启(qi)(qi)KeepAlive功 能(neng),尽管这(zhei)微不(bu)足道(dao),但在(zai)按流量(liang)计费的(de)(de)(de)(de)环境(jing)下增加了费用(yong)(yong)(yong),另(ling)一方(fang)(fang)面,KeepAlive设置(zhi)不(bu)合理时可能(neng)会(hui) 因为(wei)短暂(zan)的(de)(de)(de)(de)网络(luo)波(bo)动(dong)(dong)而断开(kai)健康(kang)的(de)(de)(de)(de)TCP连接。并且(qie),默认的(de)(de)(de)(de)KeepAlive超时需要7,200,000 MilliSeconds, 即2小(xiao)时,探测次数为(wei)5次。对于很多(duo)(duo)服(fu)务端(duan)(duan)应用(yong)(yong)(yong)程(cheng)序来(lai)说,2小(xiao)时的(de)(de)(de)(de)空(kong)闲时间太(tai)长。
因(yin)此,我们需要手工(gong)开启KeepAlive功能并(bing)设置合理的KeepAlive参数(shu)。 心跳检测步骤:
1客(ke)户(hu)端(duan)每隔一个时间间隔发(fa)生一个探测(ce)包给服务器
2客户端发包时(shi)(shi)启动一个(ge)超时(shi)(shi)定时(shi)(shi)器
3服(fu)务器端接收到检测包,应(ying)该回应(ying)一个包
4如果客户机收(shou)到服(fu)(fu)务器的应答包(bao),则说明服(fu)(fu)务器正常(chang),删除(chu)超时(shi)定时(shi)器
5如果(guo)客户端的超时(shi)定时(shi)器超时(shi),依然没有收(shou)到应(ying)答包,则(ze)说明(ming)服务器挂了