V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Mohanson
V2EX  ›  问与答

TCP 连接中服务端长时间处于 FIN_WAIT1 状态, 客户端是否无法收到 Close 事件?

  •  
  •   Mohanson · 2019-12-10 20:14:03 +08:00 · 3656 次点击
    这是一个创建于 1810 天前的主题,其中的信息可能已经有所发展或是发生改变。

    服务端正发送数据给客户端, 服务端在数据发送完毕后 Close 链接, netstat 发现这个链接进入了 FIN_WAIT1 状态, 客户端的 Read 调用也没有被终止(正常情况下, 服务端 Close 后, 客户端的 Read 会报 use of closed network connection 错误, 但服务端进入 FIN_WAIT1 的时候客户端好像不知道这个链接已经被关闭了还在傻傻等待数据).

    12 条回复    2019-12-11 09:07:35 +08:00
    wish198
        1
    wish198  
       2019-12-10 20:30:49 +08:00
    按你这个说法,你客户端得自己判断出来主动关闭呀,TCP 四次挥手看下
    Mohanson
        2
    Mohanson  
    OP
       2019-12-10 20:46:21 +08:00
    @wish198 我看过 TCP 挥手过程, FIN_WAIT1 是等待对方 ACK. 我目前发现存在题目描述的现象, 但是无法在互联网上找到确切的文字资料来证明这种现象, 因此来问一下看看是否有大佬能提供下文字资料 /Spec 等等的东西证明我的猜测是正确的还是错误的...
    lhx2008
        3
    lhx2008  
       2019-12-10 20:59:48 +08:00
    如果客户端没收到 ,就不会确认相关的信息,服务端那边就超时,会重发 Close
    alcarl
        4
    alcarl  
       2019-12-10 21:01:43 +08:00 via Android
    有可能对面的防火墙把你发过去的 fin 包过滤了,对面应用没有收到你的 fin,网络上没有其他东西的话,finwait1 阶段是内核控制的对面也是内核控制,应该会自己过度到 finwait2,对面过度到 closewait,然后才是对面应用处理。没进 closewait 客户端当然读不到 eof
    alcarl
        5
    alcarl  
       2019-12-10 21:03:33 +08:00 via Android
    @Mohanson 搜索 tcp 四次挥手?
    unixeno
        6
    unixeno  
       2019-12-10 21:16:04 +08:00   ❤️ 2
    查了一下这个问题,你可以看看这个 https://blog.huoding.com/2014/11/06/383,还有这个 https://blog.csdn.net/dog250/article/details/81697403

    在你服务端 close 之后,连接会立即进入 FIN_WAIT1 状态,如果客户端的接收缓冲区里还有数据,FIN 是不会影响客户端读取的。
    而且如果客户端一直不接收数据,以至于客户端接收队列满了,服务端的 FIN 是发不出去的,这个链接会一直处于 FIN_WAIT1 状态,只有重启系统或者等待零窗口探测包超过 tcp_orphan_retries 参数限制时触发销毁连接
    Mohanson
        7
    Mohanson  
    OP
       2019-12-10 21:48:38 +08:00 via Android
    @unixeno 谢谢,有个问题哈,如果 fin 包被拦截,那 tcp 对端是否永远也不知道这个链接被关闭了呢?
    bitcross
        8
    bitcross  
       2019-12-10 22:03:20 +08:00
    @Mohanson 对,所以才有的 keepalive 的设计,及时检测出已经”不可达”的 session

    建议你用 wireshark 之类的抓包工具在客户端抓一下包,看看 fin 包到底有没送过来
    没有的话十有八九就是路由器,防火墙之类的给拦截了,这就要在这些网络设备里检查数据包日志了
    Mohanson
        9
    Mohanson  
    OP
       2019-12-10 22:05:25 +08:00
    @bitcross 好的, 谢谢!
    unixeno
        10
    unixeno  
       2019-12-10 22:10:34 +08:00 via Android
    @Mohanson 也可以,需要你向对方发送数据,连接不存在的时候会直接 reset

    不通信的情况下,那肯定是没办法知道对方是不是还在线的
    Buges
        11
    Buges  
       2019-12-10 22:17:28 +08:00 via Android
    关键词:close()与 shutdown()的区别,自己去搜吧。
    wish198
        12
    wish198  
       2019-12-11 09:07:35 +08:00
    @Mohanson TCP 是有半关闭的,你找个 Wireshark 抓一下包就明白了,不是服务器发来 Fin,你的客户端就要自己关闭
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2803 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 11:51 · PVG 19:51 · LAX 03:51 · JFK 06:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.