为什么需要心跳包?

最近用java来写一个简单的聊天工具,接触到了这个问题。因为编写代码的时候服务端和客户端都是在本地上运行的,没有出现连接出错误的情况,客户端连接关闭之后,服务器端能正常的回收资源,且不管什么时候、间隔多长时间给客户端给服务器发送消息,服务器端都能正常的接收。最后到服务器上的时候,却出现了问题,与客户端的连接出现了问题。

为什么会出现问题?有多种原因。

1.客户端程序崩溃

2.网络运营商->NAT路由器(映射表)

 

第一个问题:

在Java实现的客户端中,当客户端关闭,都会去关闭socket连接,最终肯定也就会关闭tcp连接

1.java程序运行完毕退出和被杀进程时,也就是异常退出时,socket tcp连接会被关闭。而且是通过发送RST方式关闭tcp,不是四次挥手方式关闭tcp,不会进入TIME_WAIT状态。(一般在关闭异常连接时,使用发出RST复位标志的方式)

2.socket调用close方法时,或者在socket对象被GC回收时socket的close()方法会被调用,此时将使用四次挥手方式关闭主动tcp连接,随后进入一段时间的TIME_WAIT状态。主动调用socket的close()方法效果相同。

3.在使用new Socket(host,port)创建socket对象后,便会建立起tcp连接。

但是要注意,能进行上述关闭的前提的tcp连接还正常,能进行消息的传输,如果连接不正常了怎么办?这就要引出下面这条问题了

 

第二个问题:

因为Ip不足以分配,所以有了NAT路由器的存在,就有了映射表这个东西。映射表在每间隔一段时间之后,就会被清理一次(清理之后,服务器与客户端的连接就不正常了,消息不能正常收发),所以我们需要心跳包来维持这个映射关系。

这就有一个问题了,TCP协议不是自带KeepAlive的吗?

为什么需要在应用层做心跳,难道 TCP 不是个可靠连接吗?我们不能够依赖 TCP 做断线检测吗?比如使用 TCP 的 KeepAlive 机制来实现。应用层心跳是目前的最佳实践吗?怎么样的心跳才是最佳实践。其实TCP的KeepAlive机制是非常优秀的,但是其对于我们来说也存在一些问题。因为 TCP KeepAlive 是用于检测连接的死活,而心跳机制则附带一个额外的功能:检测通讯双方的存活状态。两者听起来似乎是一个意思,但实际上却大相径庭。该机制过于底层,我们业务层不只是需要判断连接是否正常,而且是需要双方能否进行正常交流。

 

1.Keep Alive 机制开启后,TCP 层将在定时时间到后发送相应的 KeepAlive 探针以确定连接可用性。一般时间为 7200 s,但是这个时间是可以修改的,但是修改之后,也还是不能满足我们的要求

2.某台服务器因为某些原因导致负载超高,CPU 100%,无法响应任何业务请求,但是使用 TCP 探针则仍旧能够确定连接状态,这就是典型的连接活着但业务提供方已死的状态,对客户端而言,这时的最好选择就是断线后重新连接其他服务器,而不是一直认为当前服务器是可用状态,一直向当前服务器发送些必然会失败的请求。

 

因为上面这两个原因存在,所以我们最好是在应用层实现自己的心跳机制

 

实现心跳包

客户端主要负责发送心跳包,服务器接收心跳包,来维持连接。

服务器也要对所有客户端进行活跃性扫描,以便以清理未活跃的客户端,扫描时间间隔应该长于客户端发送心跳包的间隔

 

 

即时通信网:http://www.52im.net/

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值