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

2020-03-12 11:09:24 +08:00
 gutao1994

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

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

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

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

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

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

这是谁跟你说的?

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

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

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

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

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

© 2021 V2EX