如图所示,执行同时关闭连接的双方,如果客户端的 fin 包出现延迟,有没有可能会出现这种情况?
https://wenda.swoole.com/storage/article-column/x2r4yaeWn1GPJTZipLhmV3d3iNxWy1J5WHhcV5cw.jpeg
1
gutao1994 OP 客户端 fin 包出现延迟,导致客户端回复服务端的 ack 包先达到服务器,服务器从原先的 fin_wait1-->closing 变成 fin_wait1-->fin_wait2,有可能会出现这种情况吗?
|
2
index90 2020-03-12 12:40:51 +08:00 3
|
3
opengps 2020-03-12 13:09:30 +08:00
适当跳出规则之外盲答:必然有!
我当初做 GPS 通信,测试 socket 连接的时候,用了一个非常原始的做法来检测连接可用性:拔网线!这会导致断开握手根本互相发不出去,从而导致连接已经失活。最终,我的方案里只相信自己的心跳回复验证来判断连接存活。 |
4
coer 2020-03-12 13:24:32 +08:00 via iPad
tcpip 详解 里的 tcp 状态转移图里有这种情况
|
7
index90 2020-03-12 14:21:57 +08:00
client 发出的 fin 包不会晚于它 ack 包到达 server (或者说被 server 确认接收)
why ? 因为 TCP 包是有序的啊 |
8
index90 2020-03-12 14:24:30 +08:00
发送窗口和接收窗口了解一下
|
10
tyrantZhao 2020-03-12 14:29:08 +08:00
有可能,但是状态怎么变化,不太清楚
|
11
index90 2020-03-12 14:42:20 +08:00
@gutao1994 #8 补充一下,首先 TCP 里面的 seq (包的序列号)和 ack (应答序列号)确保了 TCP 通讯的有序性。如果你不清楚建议你再细读一下 TCP 协议。
然后你说的 fin 包延迟,是有可能发生的,假设没有接收窗口的情况下,client 的 ACK 包是不可能被接收的,因为他的序列号不对。如果有接收窗口的情况下,ACK 包会被接收到接收窗口里(可以理解成 buffer ),但是会等到 fin 包被接收后,有序地返回操作系统。 |
12
gutao1994 OP @index90
tcp 的序列号字段只有在下面两种情况的任意一种才有意义: 1. 数据字段至少包含一个字节 2. 这是一个 SYN 段,或者是 FIN 段,或者是 RST 段。 因为 ack 不符合上述的两个条件,所以 ack 包被接收的时候,是不会去考虑他的序列号。 所以也就不存在 ack 包必须在 fin 包之后被接收。 这种说法对吗? |
13
index90 2020-03-12 15:19:45 +08:00
“ tcp 的序列号字段只有在下面两种情况的任意一种才有意义:
1. 数据字段至少包含一个字节 2. 这是一个 SYN 段,或者是 FIN 段,或者是 RST 段 ” 这是谁跟你说的? TCP 的有序性是依赖序列号和确认序列号保证的,哪有分什么阶段啊。还是翻出大学教材重新读一下,半小时,比你在这里问快多了。 |
14
maplelin 2020-03-12 18:22:33 +08:00
如果极端情况就恢复到单端发起关闭的状态了,比如客户端 FIN 包丢失了,服务端永远没有收到客户端的状态,这样就是正常走服务器发起 FIN 的流程了。延迟的话状态和同时发起没有区别,服务端会按序号处理 FIN 和 ACK。
|
15
ysmood 2020-03-12 18:56:21 +08:00
@index90 有可能的吧。TCP 只是个协议,传输层不一定要按照协议传输,比如恶意程序劫持 TCP 包然后不按照顺序传输。只不过通用 TCP 实现都会有个 buffer 包然后通过解读包的内容重新排序,所以你在应用层 read tcp 包的时候感觉顺序是既定的。所以要看哪个层面在解读这个问题,是 tcp 实现层还是应用层。
|
17
coer 2020-03-13 01:10:05 +08:00 via Android
|
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 不知道你在说啥 |