服务端正发送数据给客户端, 服务端在数据发送完毕后 Close 链接, netstat 发现这个链接进入了 FIN_WAIT1 状态, 客户端的 Read 调用也没有被终止(正常情况下, 服务端 Close 后, 客户端的 Read 会报 use of closed network connection 错误, 但服务端进入 FIN_WAIT1 的时候客户端好像不知道这个链接已经被关闭了还在傻傻等待数据).
1
wish198 2019-12-10 20:30:49 +08:00
按你这个说法,你客户端得自己判断出来主动关闭呀,TCP 四次挥手看下
|
2
Mohanson OP @wish198 我看过 TCP 挥手过程, FIN_WAIT1 是等待对方 ACK. 我目前发现存在题目描述的现象, 但是无法在互联网上找到确切的文字资料来证明这种现象, 因此来问一下看看是否有大佬能提供下文字资料 /Spec 等等的东西证明我的猜测是正确的还是错误的...
|
3
lhx2008 2019-12-10 20:59:48 +08:00
如果客户端没收到 ,就不会确认相关的信息,服务端那边就超时,会重发 Close
|
4
alcarl 2019-12-10 21:01:43 +08:00 via Android
有可能对面的防火墙把你发过去的 fin 包过滤了,对面应用没有收到你的 fin,网络上没有其他东西的话,finwait1 阶段是内核控制的对面也是内核控制,应该会自己过度到 finwait2,对面过度到 closewait,然后才是对面应用处理。没进 closewait 客户端当然读不到 eof
|
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 参数限制时触发销毁连接 |
7
Mohanson OP @unixeno 谢谢,有个问题哈,如果 fin 包被拦截,那 tcp 对端是否永远也不知道这个链接被关闭了呢?
|
8
bitcross 2019-12-10 22:03:20 +08:00
@Mohanson 对,所以才有的 keepalive 的设计,及时检测出已经”不可达”的 session
建议你用 wireshark 之类的抓包工具在客户端抓一下包,看看 fin 包到底有没送过来 没有的话十有八九就是路由器,防火墙之类的给拦截了,这就要在这些网络设备里检查数据包日志了 |
10
unixeno 2019-12-10 22:10:34 +08:00 via Android
|
11
Buges 2019-12-10 22:17:28 +08:00 via Android
关键词:close()与 shutdown()的区别,自己去搜吧。
|