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

关于 tcp 同时关闭的一个猜想

  •  
  •   gutao1994 · 2020-03-12 11:09:24 +08:00 · 2413 次点击
    这是一个创建于 511 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如图所示,执行同时关闭连接的双方,如果客户端的 fin 包出现延迟,有没有可能会出现这种情况?

    https://wenda.swoole.com/storage/article-column/x2r4yaeWn1GPJTZipLhmV3d3iNxWy1J5WHhcV5cw.jpeg

    18 条回复    2020-03-13 03:04:58 +08:00
    gutao1994
        1
    gutao1994   2020-03-12 11:13:15 +08:00
    客户端 fin 包出现延迟,导致客户端回复服务端的 ack 包先达到服务器,服务器从原先的 fin_wait1-->closing 变成 fin_wait1-->fin_wait2,有可能会出现这种情况吗?
    index90
        2
    index90   2020-03-12 12:40:51 +08:00   ❤️ 3
    opengps
        3
    opengps   2020-03-12 13:09:30 +08:00
    适当跳出规则之外盲答:必然有!
    我当初做 GPS 通信,测试 socket 连接的时候,用了一个非常原始的做法来检测连接可用性:拔网线!这会导致断开握手根本互相发不出去,从而导致连接已经失活。最终,我的方案里只相信自己的心跳回复验证来判断连接存活。
    coer
        4
    coer   2020-03-12 13:24:32 +08:00 via iPad
    tcpip 详解 里的 tcp 状态转移图里有这种情况
    gutao1994
        5
    gutao1994   2020-03-12 13:43:30 +08:00
    @coer 能详细说明一下吗
    gutao1994
        6
    gutao1994   2020-03-12 13:44:50 +08:00
    @index90 文中也没说到 fin 包延迟的情况啊。。。
    index90
        7
    index90   2020-03-12 14:21:57 +08:00
    client 发出的 fin 包不会晚于它 ack 包到达 server (或者说被 server 确认接收)
    why ?
    因为 TCP 包是有序的啊
    index90
        8
    index90   2020-03-12 14:24:30 +08:00
    发送窗口和接收窗口了解一下
    gutao1994
        9
    gutao1994   2020-03-12 14:27:53 +08:00
    @index90 好的,谢谢
    tyrantZhao
        10
    tyrantZhao   2020-03-12 14:29:08 +08:00
    有可能,但是状态怎么变化,不太清楚
    index90
        11
    index90   2020-03-12 14:42:20 +08:00
    @gutao1994 #8 补充一下,首先 TCP 里面的 seq (包的序列号)和 ack (应答序列号)确保了 TCP 通讯的有序性。如果你不清楚建议你再细读一下 TCP 协议。
    然后你说的 fin 包延迟,是有可能发生的,假设没有接收窗口的情况下,client 的 ACK 包是不可能被接收的,因为他的序列号不对。如果有接收窗口的情况下,ACK 包会被接收到接收窗口里(可以理解成 buffer ),但是会等到 fin 包被接收后,有序地返回操作系统。
    gutao1994
        12
    gutao1994   2020-03-12 14:50:54 +08:00
    @index90

    tcp 的序列号字段只有在下面两种情况的任意一种才有意义:
    1. 数据字段至少包含一个字节
    2. 这是一个 SYN 段,或者是 FIN 段,或者是 RST 段。

    因为 ack 不符合上述的两个条件,所以 ack 包被接收的时候,是不会去考虑他的序列号。
    所以也就不存在 ack 包必须在 fin 包之后被接收。

    这种说法对吗?
    index90
        13
    index90   2020-03-12 15:19:45 +08:00
    “ tcp 的序列号字段只有在下面两种情况的任意一种才有意义:
    1. 数据字段至少包含一个字节
    2. 这是一个 SYN 段,或者是 FIN 段,或者是 RST 段 ”

    这是谁跟你说的?

    TCP 的有序性是依赖序列号和确认序列号保证的,哪有分什么阶段啊。还是翻出大学教材重新读一下,半小时,比你在这里问快多了。
    maplelin
        14
    maplelin   2020-03-12 18:22:33 +08:00
    如果极端情况就恢复到单端发起关闭的状态了,比如客户端 FIN 包丢失了,服务端永远没有收到客户端的状态,这样就是正常走服务器发起 FIN 的流程了。延迟的话状态和同时发起没有区别,服务端会按序号处理 FIN 和 ACK。
    ysmood
        15
    ysmood   2020-03-12 18:56:21 +08:00
    @index90 有可能的吧。TCP 只是个协议,传输层不一定要按照协议传输,比如恶意程序劫持 TCP 包然后不按照顺序传输。只不过通用 TCP 实现都会有个 buffer 包然后通过解读包的内容重新排序,所以你在应用层 read tcp 包的时候感觉顺序是既定的。所以要看哪个层面在解读这个问题,是 tcp 实现层还是应用层。
    xiadada
        16
    xiadada   2020-03-13 00:28:03 +08:00 via iPhone
    @index90 这个不对啊.... tcp 是双工的。
    他发出去的 和 接受别人给他可以有两个
    coer
        17
    coer   2020-03-13 01:10:05 +08:00 via Android
    index90
        18
    index90   2020-03-13 03:04:58 +08:00
    当前 Client 的序号是 x,Server 的序号是 y
    Client Server
    FIN_WAIT --seq=x+1,ack=y+1--> 未到达
    CLOSING <--seq=y+1,ack=x+1-- FIN_WAIT
    TIME_WAIT --seq=x+2,ack=y+2--> FIN_WAIT2

    LZ 的猜想是,当 seq=x+1,ack=y+1 这个包比 seq=x+2,ack=y+2 的包晚到的时候,会不会出现 Server 变成了 FIN_WAIT2 状态。答案是不会!因为 Server 在等待 seq=x+1 这个包。等不到就会要求 Client 重传,直到收到 seq=x+1 这个包之后,seq=x+2 的包才有效。


    @ysmood #15 和你说的什么应用层没关系,TCP 的有序是指能保证接收方接收数据包的顺序等于发送方发送的顺序

    @xiadada #16 不知道你在说啥
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   937 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:31 · PVG 04:31 · LAX 13:31 · JFK 16:31
    ♥ Do have faith in what you're doing.