心跳包必要性与策略选择

一、CS模型中如何相互知晓状态

为什么需要心跳包?

在传统的CS模型中,客户端与服务端相互发送消息的过程中,是需要知道相互之间的状态的,因为客户端随时可能给服务端发送消息。在聊天过程中,是不可能客户端随时给服务端发送消息,真实情况是服务端收到某个客户端的消息之后推送过来。在这个过程中,服务器需要知道客户端是否可用的。

服务端要想知道客户端是否可用,最大的问题在于可能客户端异常地断开了,但是服务器没有收到断开的这个情况,所以服务器没有释放这个socket,它认为还连接着,此时,他会向该客户端发送消息,而在发送消息之后会发生异常。其实该过程是一个浪费的,因为服务端已准备好数据准备发送,但是发送的时候才失败,现在重新进行一个重连,重新创建数据包,这是一个非常浪费的过程。这是我们需要心跳包的原因。

 

二、从TCP理论来说不需要心跳包-客户端服务器直连

如果将客户端与服务端同时部署在自己的电脑上,两个进程之间通过socket相互传递消息的时候,这时候是不需要心跳包来维持的。只要进程不断开,随时可用发送和接收数据。

 

需要心跳包的情况:

--程序崩溃、防火墙

--网络运营商(ISP) --> NAT路由器(映射状态表)

 

程序崩溃的时候,可能会触发服务端没有收到程序崩溃的情况,服务端也不知道需要释放客户端的资源。

计算机与计算机之间相互是有防火墙的,而这个防火墙随时可以做到一个策略,随时可以断开socket连接,而断开的时候可能不会进行四次挥手,服务端或者客户端没有收到连接断开的消息,此时会认为连接还可用,随时还想发送数据,发送的时候才知道连接不可用。

引起网络断开的大头是网络运营商ISP,它在传输数据的过程中有一个东西叫NAT路由器。路由器的主要作用是将客户端所有的状态通过NAT路由器进行映射,然后再通过映射的端口进行连接服务器,这个过程中存在一个映射表过期的情况,一旦映射表过期了,就是数据不能通过NAT路由器进行转发了,所以数据最终发送的时候会出现无法发送的情况,此时socket连接也是连接异常的状态。此时,socket连接是接收不到断开连接的消息的。

 

三、NAT路由器的原理

ISP是网络运营商,它有一个非常大型的路由器,这个大型路由器组建了一个大型局域网,大型局域网连接了所有的电脑、手机、打印机等所有可以联网的设备,甚至也可以是路由器。家里的路由器就是连接到了网络运营商的大型路由器上。每个电脑都被分配了局域网的某个ip地址,以及通信都是连接到路由器上面的。这样的情况下,比如电脑的ip 192.168.0.101其实是局域网的ip地址,它仅仅只是在路由器上挂了一个号,用于说明它是路由器下面的哪个子的电脑。

路由器有一个对外的公共的ip地址 82.10.250.19,服务器也是一个外网地址,两个外网地址之间是可以直接进行连接的。连接之后所有的信息都是通过路由器进行传输的,也就是说对服务器而言,所有的电脑设备都是被屏蔽的,它只知道有一个大的客户端向它进行了连接,这个大的客户端就是82.10.250.19。

 

四、电脑与服务器之间的连接

电脑通过局域网连接路由器,这个路由器有一个全局对外的ip地址82.10.250.19,然后通过网络运营商连接到server服务器。Server的ip地址一定是公网的ip地址才可以连接到。如果服务端是局域网的ip地址的话,对于NAT路由器来说是无法访问到的,它必须连接到对外的公共的ip地址。

 

五、NAT路由器的映射表

1、

对于某个客户端而言,只要客户端的ip地址没变,同时客户端对外的端口没变,那么NAT路由器对外公布的往其它Server连接的ip和地址将不会改变。也就是说,一个客户端通过NAT路由器之后,如果此时NAT路由器是一个80端口,那么它连接到server1的时候使用的是80端口去连接,连接到server2的时候也是使用80端口去连接。只要客户端的ip地址和端口不变,那么它就将是这样一个结构。

这样的结构是一个一对多的结构,对于NAT路由器而言,它是一个一对多的(多个服务端)。

这样的结构安全性是比较低的,因为只要客户端的ip地址和端口不变,那么NAT路由器的ip地址和端口就不变,那么Server1、Server2只要连接过一次客户端,那么它就可以反向连接客户端。也就是说,可以通过client连接server1,也可以通过server2来主动反向连接client,这是一个双向的方式。这样的方式,数据传输快,但是安全性较低。

2、

客户端ip和端口不变,但是连接的server端是变化的,那么它对外的端口就是不同的。server1只能通过上面的端口来收发数据,Server2也只能通过下面的端口来收发数据。如果Server2想通过Server1的端口来反向连接客户端,是不会成功的。因此,它的安全性相对来说比较高。

 

六、NAT超时时间

如果移动在3G/2G网络下,如果数据在5分钟之内不进行任何的数据收发,那么,NAT内部维持的映射表将会自动被删除掉。所以,必须在5分钟之内进行一次数据的收发,确保维持这个映射表。其它依次类推。

 

七、心跳包的作用

客户端与服务器之间相互告知状态

通过定时发送信息,让中间的运营商的NAT路由表得以维持;避免路由表过期带来的异常中断

由于其约定性、定时性所以称为心跳包

 

八、心跳策略选择

1、

TCP :  KeepAlive 7200 2H ACK(每间隔7200s发送一次,2小时发送一次,发送之后会有ACK的回送包,从而达到确认连接活跃性的目的)

TCP : KeepAlive仅代表连接得以保持,而不代表对方的业务层是否可以消费数据

(当两个socket连接之后,当一个socket给另一个socket发送一个keepalive连接消息的时候,这个数据包仅仅只在TCP的传输层就被消费掉了,然后回送一个ack的回送包,但是这个消息并不会上升到业务层。这样的机制可以确保对上层的无感知性,但同时不能保证业务层已经崩溃了。业务层可能由于某些原因导致死锁或者宕机,而底层的socket连接还是畅通的,这种情况下整个系统是瘫痪的,但是通过KeepAlive进行连接,此时得到的状态是正常的。这种情况是不对的,应该得到系统的准确状态,同时,由于每隔2个小时发送一次,此时运营商NAT的连接早已中断了,这个连接一般而言发送这个KeepAlive消息的时候收到的是已经错误中断的消息)

HTTP : Keep-Alive 意图在于连接复用,同一个连接上串行方式传递请求-响应数据

2、

这个数据包只能发送一个字节,传递的是一个int值,取的是低八位。

另一个客户端可以通过SO_OOBINLINE来设置是否感知业务层。但是如果要感知业务层,需要把它往业务层抛去 ,业务层收到这个数据之后,由于它的区间是在0~255之间,跟整个业务层的冲撞是非常非常大的,从而导致整个业务层的逻辑进行调整,这是非常危险的,一般不这样处理。

但是也可以不往业务层抛,仅仅用来确认连接是否可靠,此时,比前面的KeepAlive更加优秀。

 

九、心跳数据包

 

十、

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章