本地测试,随便找了个 ip 去 curl 。然后用 Wireshark 去抓包。
过滤项指定好 IP (比如 ip.addr == 183.6.231.253 )和 TCP 的本地端口( tcp.port == 53109 )。
结果是 TCP 的断开连接一直都是三次挥手,而不是广为流传的四次挥手。
我就想复现下怎么四次挥手。
想问下什么情况下三次,什么时候四次?我感觉三次的情况还挺多的。
1
Conty 2022-07-30 18:17:03 +08:00
两边都没有东西可发的时候。
|
2
hxndg 2022-07-30 18:19:29 +08:00
日常发包,tls 的报文会跟着 tcp 握手的最后一个报文一块过来,从而节省握手的时间
你这个 case 是一样的,只不过是 fin 和 ack 报文一块过来,看中间那个包,所以实际上和四次握手是一样的。 不要被四次或者三次尬住,那个只是一个说法,本质没变的 |
3
hxndg 2022-07-30 18:20:34 +08:00
如果另外一边数据没发送完,这个时候必然就四次了,因为需要先 ack peer fin ,然后再 fin 本端。
|
4
disk 2022-07-30 18:21:30 +08:00
delayed ACK ,把二三次的挥手合并了,详见 https://datatracker.ietf.org/doc/html/rfc1122#page-96
|
5
codehz 2022-07-30 18:29:56 +08:00
只是服务器合并了一个 ACK 和 FIN 而已,教科书级别的 tcp 是允许一边关闭然后另一边继续发的,但是对于 http 服务器来说客户端关闭上行通道,同时响应已经发送完毕的情况下,没有必要继续保留连接了
|
7
hankai17 2022-07-31 07:49:25 +08:00
能复现吗? 像延迟 ack 但这个延迟有点高 居然可以等到一个系统调用
|
8
ysc3839 2022-07-31 09:15:38 +08:00 via Android
个人觉得不应该叫“四次挥手”,而应该叫“两端关闭”,这里的两端指的是两个发送数据的端。
曾经在网上看到一个问题,大概是想通过抓包得到的数据自己实现一个软件的通信协议,写完代码后发现服务器一直没有反应,而发送的数据并没区别。提问者在经过一番对比后发现:“为什么这个软件通信的时候,最后关闭连接只有两次挥手?” 最后发现客户端发完数据后要先关闭发送,服务器才会开始处理并回复。因为客户端已经关闭了,服务器最后关闭时看上去就只有“两次挥手”。 当理解了所谓 TCP 挥手其实是两端关闭后,楼主遇到的这个情况也就很好理解了:客户端先向服务器发送 FIN 请求关闭,服务器收到后回复 ACK 确认关闭,同时也附带 FIN 请求关闭,客户端收到后回复 ACK 确认关闭,此时两端都已关闭,就是断开连接了。 |
9
iseki 2022-07-31 11:53:39 +08:00 via Android
开 TCP nodelay 试试
|