V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fstar
V2EX  ›  程序员

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

  •  
  •   fstar · 2022-07-30 18:06:17 +08:00 · 2392 次点击
    这是一个创建于 625 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    第 1 条附言  ·  2022-07-30 21:39:15 +08:00
    查阅了一些文章,感觉是因为 TCP 延迟确认机制导致的。

    所谓 TCP 延迟确认,就是让要发出去的 TCP 包先不开车,等一等,比如等个 40ms ,看看有没有下一个 TCP 包,有的话一起上车。此举意在减少包的数量。

    回到关闭 TCP 连接。第二次挥手,ACK 先上了车,然后中间没有其他 TCP 包,然后 FIN 也上了车,所以最后是 ACK 和 FIN 一起出发了,看起来就像是三次挥手了。
    10 条回复    2022-07-31 17:48:54 +08:00
    Conty
        1
    Conty  
       2022-07-30 18:17:03 +08:00
    两边都没有东西可发的时候。
    hxndg
        2
    hxndg  
       2022-07-30 18:19:29 +08:00
    日常发包,tls 的报文会跟着 tcp 握手的最后一个报文一块过来,从而节省握手的时间

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

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

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

    当理解了所谓 TCP 挥手其实是两端关闭后,楼主遇到的这个情况也就很好理解了:客户端先向服务器发送 FIN 请求关闭,服务器收到后回复 ACK 确认关闭,同时也附带 FIN 请求关闭,客户端收到后回复 ACK 确认关闭,此时两端都已关闭,就是断开连接了。
    iseki
        9
    iseki  
       2022-07-31 11:53:39 +08:00 via Android
    开 TCP nodelay 试试
    disk
        10
    disk  
       2022-07-31 17:48:54 +08:00
    @rsonghao 搜索引擎,这不像是个疑难或很难问出的问题,大概率有别人提问和研究过。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5057 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 53ms · UTC 05:37 · PVG 13:37 · LAX 22:37 · JFK 01:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.