探测方式
- UDP心跳机制
- TCP握手消息
- TCP保活机制
- select机制
UDP心跳机制
自定义心跳消息头,客户端主动上报,服务端接受后不回应。
服务端根据心跳上报情况判断客户端是否仍然在线。
(UDP正常上报 -> 默认设备正常 -> 默认TCP正常)
(UDP正常上报 -> TCP正常;UDP检测本地TCP状态,条件满足才上报)
TCP握手消息
自定义心跳消息头,一般客户端主动发送,服务端接受后主动回应。
客户端根据回应情况判断服务端是否仍然在线。
为不影响连接socket的正常使用,一般需要再开一个线程,专门用于检测对方状态。
或者考虑select机制实现连接socket的异步。
TCP保活机制
保活机制:一种在不影响数据流内容的情况下探测对方的方式。它是由一个保活计时器实现的。当计时器被激发, 连接端将发送一个保活探测(简称保活)报文 , 另一端接收报文的同时会发送一个ACK作为响应。
保活功能在默认情况下是关闭的,TCP连接的任何一端都可以请求打开这一功能。保活功能可以被设置在连接的一端、两端,或者两端都没有。
保活探测报文为一个空报文段(或1个字节),序列号等于对方主机发送的ACK报文的最大序列号减1。
因为这一序列号的数据段已经被成功接收,所以不会对到达的报文段造成影响,但探测报文返回的响应可以确定连接是否仍在工作。接收方收到该报文以后,会认为是之前丢失的报文,所以不会添加进数据流中。但是仍然要发送一个ACK确认。
探测及其响应报文丢失后都不会重传。探测方主动不重传,相应方的ACK报文并不能自己重传,所以需要保活探测数。
请求端通过响应的ACK还可判断对方TCP是正常关闭,还是异常关闭。
探测到对方主机的4种状态
正常
对方TCP正常响应ACK
请求端将保活计时器重置,重新计时。
崩溃
对方TCP不响应ACk
超过保活探测数后,请求端认为对方不在线,关闭连接。
崩溃并重启
对方TCP响应一个重置报文段
请求端关闭连接
在工作但不响应
对方TCP因其他原因(网络),未响应ACK。
超过保活探测数后,请求端认为对方不在线,关闭连接。
TCP KeepAlive开启
在TCP协议机制,SO_KEEPALIVE默认是2小时的心跳频率,且KeepAlive默认关闭。
用setsockopt将SOL_SOCKET.SO_KEEPALIVE设置为1打开TCP保活机制。
再根据现场情况设置三个参数tcp_keepalive_time、tcp_keepalive_probes、tcp_keepalive_intvl。
tcp_keepalive_time:连接闲置后,发KeepAlive的ACK包的等待时间;
tcp_keepalive_probes:发送未响应ACk包的最大次数,超过则认为对方不在线;
tcp_keepalive_intvl:两个ACK包之间的时间间隔;
select机制
TCP建立连接后,通过select并recv数据 检测TCP的连接状态。
前提:发送方不能发送长度为0的数据;
开启select检测,一旦TCP断连,接收方select中的socket将被激活,并执行recv收到空数据,由此说明TCP已断连。
若recv接收数据的长度为-1,说明TCP异常关闭;
若recv接收数据的长度为0,说明TCP正常关闭。