文章详情
心跳包与TCP连接有什么关系?

TCP长连接,短连接及心跳包功能

TCP连接简介

当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接, 当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接, 连接的建立是需要三次握手的, 而释放则需要4次握手, 所以说每个连接的建立都是需要资源消耗和时间消耗。

TCP经典的三次握手示意图

TCP是一种可靠的,面向连接的全双工传输层协议,TCP连接的建立是一个三次握手的过程。如图所示:

  1. 客户端发送一个标识了SYN的数据段,表示期望与服务器建立连接,此数据段的序列号(seq)为client_isn;
  2. 服务器回复一个标识了SYN+ACK的数据段,此数据段的序列号(seq)为server_isn,即:seq=server_isn, 确认序列号ack为客户端的序列号加1,即ack=client_isn+1,以此作为对客户端 的SYN报文的确认;
  3. 客户端发送一个标识了ACK的数据段,此数据段的序列号(seq)为 client_isdn+1,即:seq=client_isn+1;确认序列号为服务器的序列号加1,即ack=server_isn+1,以此作为对服务器的SYN报文的确认。

 

经典的四次握手关闭图:

假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了", 但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了, 但是我还没准备好, 请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端, 好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态, 如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。 Ok,TCP连接就这样关闭了!

 

 

整个过程,Client端所经历的状态如下:

 

 

而Server端所经历的过程如下:

注意事项及疑点问答

在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。

问题1:为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手

问题2:为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:按理论说,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假想网络是不可靠的,有可能某一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。

长连接与短连接

长连接: 指在一个TCP连接上可以连续发送多个数据包, 在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接; 一般需要自己做在线维持。

短连接: 指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接; 它的优点是:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段

比如http的,只是连接、请求、关闭,过程时间较短,服务器若是一段时间内没有收到请求即可关闭连接。 其实长连接是相对于通常的短连接而说的,也就是长时间保持客户端与服务端的连接状态。

什么时候用长连接,短连接?

长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。 而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。 总之,长连接和短连接的选择要视情况而定。

什么是心跳包?

心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。

 

用来判断对方(设备,进程或其它网元)是否正常运行,采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经离线。用于检测TCP的异常断开。基本原因是服务器端不能有效的判断客户端是否在线,也就是说,服务器无法区分客户端是长时间在空闲,还是已经掉线的情况。此时就会用到心跳包机制,它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。如果服务端几分钟内没有收到客户端信息则视客户端断开。

比如有些通信软件长时间不使用,要想知道它的状态是在线还是离线就需要心跳包,定时发包收包。发包方:可以是客户也可以是服务端,看哪边实现方便合理,一般是客户端。服务器也可以定时发心跳下去。一般来说,出于效率的考虑,是由客户端主动向服务器端发包,而不是服务器向客户端发。客户端每隔一段时间发一个包,使用TCP的,用send发,使用UDP的,用sendto发,服务器收到后,就知道当前客户端还处于“活着”的状态,否则,如果隔一定时间未收到这样的包,则服务器认为客户端已经断开,进行相应的客户端断开逻辑处理。

总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

心跳检测步骤

  1. 客户端每隔一个时间间隔发生一个探测包给服务器;
  2. 客户端发包时启动一个超时定时器;
  3. 服务器端接收到检测包,应该回应一个包;
  4. 如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器;
  5. 如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了。

Conextop串口联网模块心跳包功能

在网络透传模式下,用户可以选择让NePort网口模块发送心跳包,心跳包可以向网络服务器端发送,也可以向串口设备端发送。向网络端发送主要目的是为了 与服务器保持连接,Conextop网口模块心跳包可支持TCP Client,TCP Server 及UDP模式。在服务器向设备发送的固定查询指令的应用中,为了减少通信流量,用户可以选择向串口设备端发送心跳包(查询指令),来代替从服务器发送查询指令。NePort系列,NeBoard系列产品都支持即可以向串口发送心跳包,又可以向网络发送心跳包。