TCP 断开连接什么情况下挥手只有 3 次?

2022-07-30 18:06:17 +08:00
 fstar

本地测试,随便找了个 ip 去 curl 。然后用 Wireshark 去抓包。

过滤项指定好 IP (比如 ip.addr == 183.6.231.253 )和 TCP 的本地端口( tcp.port == 53109 )。

结果是 TCP 的断开连接一直都是三次挥手,而不是广为流传的四次挥手。

我就想复现下怎么四次挥手。

想问下什么情况下三次,什么时候四次?我感觉三次的情况还挺多的。

2408 次点击
所在节点    程序员
10 条回复
Conty
2022-07-30 18:17:03 +08:00
两边都没有东西可发的时候。
hxndg
2022-07-30 18:19:29 +08:00
日常发包,tls 的报文会跟着 tcp 握手的最后一个报文一块过来,从而节省握手的时间

你这个 case 是一样的,只不过是 fin 和 ack 报文一块过来,看中间那个包,所以实际上和四次握手是一样的。

不要被四次或者三次尬住,那个只是一个说法,本质没变的
hxndg
2022-07-30 18:20:34 +08:00
如果另外一边数据没发送完,这个时候必然就四次了,因为需要先 ack peer fin ,然后再 fin 本端。
disk
2022-07-30 18:21:30 +08:00
delayed ACK ,把二三次的挥手合并了,详见 https://datatracker.ietf.org/doc/html/rfc1122#page-96
codehz
2022-07-30 18:29:56 +08:00
只是服务器合并了一个 ACK 和 FIN 而已,教科书级别的 tcp 是允许一边关闭然后另一边继续发的,但是对于 http 服务器来说客户端关闭上行通道,同时响应已经发送完毕的情况下,没有必要继续保留连接了
rsonghao
2022-07-30 22:41:02 +08:00
@disk 想问问大佬是怎么在 rfc 里找到的,想学习这个找答案的能力😂
hankai17
2022-07-31 07:49:25 +08:00
能复现吗? 像延迟 ack 但这个延迟有点高 居然可以等到一个系统调用
ysc3839
2022-07-31 09:15:38 +08:00
个人觉得不应该叫“四次挥手”,而应该叫“两端关闭”,这里的两端指的是两个发送数据的端。

曾经在网上看到一个问题,大概是想通过抓包得到的数据自己实现一个软件的通信协议,写完代码后发现服务器一直没有反应,而发送的数据并没区别。提问者在经过一番对比后发现:“为什么这个软件通信的时候,最后关闭连接只有两次挥手?”
最后发现客户端发完数据后要先关闭发送,服务器才会开始处理并回复。因为客户端已经关闭了,服务器最后关闭时看上去就只有“两次挥手”。

当理解了所谓 TCP 挥手其实是两端关闭后,楼主遇到的这个情况也就很好理解了:客户端先向服务器发送 FIN 请求关闭,服务器收到后回复 ACK 确认关闭,同时也附带 FIN 请求关闭,客户端收到后回复 ACK 确认关闭,此时两端都已关闭,就是断开连接了。
iseki
2022-07-31 11:53:39 +08:00
开 TCP nodelay 试试
disk
2022-07-31 17:48:54 +08:00
@rsonghao 搜索引擎,这不像是个疑难或很难问出的问题,大概率有别人提问和研究过。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/869666

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX