wikipedia:A keepalive (KA) is a message sent by one device to another to check that the link between the two is operating, or to prevent the link from being broken.
实现方式:在完成TCP三次握手之后,TCP连接就建立了。为了防止连接一端在没有通知对方的情况下就断开连接,在TCP连接上没有数据交互的一定时间,通常由server端发起keepalive数据段,并每隔一定时间重试发起keepalive数据段,直到接收到对端发送的ACK报文。
linux关于TCP keepalive相关的配置参数:
# 如果7200秒都没有数据交互,就发送keepalive
cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
# 每两个keepalive消息发送间隔
cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
# keepalive重试次数,如果次数已经达到,但是对端还是没有回应,则断开连接(发送RST报文)
cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
以上为centos 7上的默认配置
默认配置的时间太长,不利于我们实验,故修改成如下配置:
echo 10 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
进入正文:抓包,查看keepalive报文的结构:
这里使用packetdrill工具建立TCP连接,并通过tcpdump抓包,在wireshark中展示包详情、及交互过程。
-
使用tcpdump提前监听8080端口的数据包,并将抓包保存到trykeepalive.pcap(该文件下载地址:https://pan.baidu.com/s/1z06DpyQmi8yYhBJplS5Bkw 提取码: saf2)
tcpdump -i any -nn tcp port 8080 -w trykeepalive.pcap
这里之所以只抓8080端口的数据包packetdrill 默认监听8080端口
-
使用packetdrill工具建立TCP连接
使用的文件
tcp.pkt
:--tolerance_usecs=100000 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 // 打开keepalive选项 +0 setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 +0 bind(3, ..., ...) = 0 +0 listen(3, 1) = 0 // 三次握手 +0 < S 0:0(0) win 20 <mss 1000> +0 > S. 0:0(0) ack 1 <...> +.1 < . 1:1(0) ack 1 win 20 +0 accept(3, ..., ...) = 4 // 防止退出 +0 `sleep 1000000`
启动:
packetdrill tcp.pkt
-
使用wireshark打开
trykeepalive.pcap
。
image.png
报文解读:
1-3: TCP三次握手
4:10秒内没有数据交互,server发起keepalive数据段
5:5秒内没有收到对端的ACK消息,server重试发起keepalive数据段
6:同5
7:3次重试后,均为收到对端的ACK消息,server主动断开连接
keepalive报文的特点如下:
- 带有ACK Flag
- Seq设置为正常的Seq - 1
- 不携带数据(Len = 0)