前一段时间在使用Wireshark抓包的时候,闲着没事跟踪了一下TCP的stream,发现了一个神奇的现象,如下图:
这是此次TCP连接关闭时的报文,不知道大家有没有发现什么怪怪的地方,没错,那就是报文发送的顺序。
大家一定很熟悉下面这张图:
这张图被很多的网站和文章所引用,一般大家理解的TCP四次挥手就是这张图了,可是如果按照上图中的流程来的话(为了方便我们将192.168.0.108称为a,将36.110.213.227称为b):
- 首先a向b发送FIN报文请求关闭连接,a的FIN报文的Sequence number为627。
- 此时b收到a的FIN报文应该对a回复一个确认的ACK报文,自己的Sequence number为219,确认的Acknowledgement number应该为a的FIN报文Sequence number +
1即627 + 1 = 628(因为SYN/FIN报文虽然不携带数据但是还是要占用1个字节的序列号)。 - b待到自己对a的传输结束后向a发送FIN报文,自己的Sequence number为219(ACK报文可以携带数据,但是不携带数据时不占用序列号所以还是219),确认的Acknowledgement
number为627 + 1 = 628。 - a收到b的FIN报文回复一个ACK确认报文,自己的Sequence number为627 + 1 = 628,确认的Acknowledgement
number为219 + 1 = 220。
这个结果与我们抓包的结果并不相同,首先在第二步,b并没有发送回复a FIN的ACK报文,而是直接发送了自己的FIN报文,而且我们可以注意到b FIN报文的对a要求的Acknowledgement number是627,但是之前a发送FIN报文时已经使用了627.
这都跟我之前认知中的TCP四次挥手步骤对不上,为什么会这样?
我翻阅了经典著作《TCP/IP详解卷一:协议》,才发现经常被引用的图二只是TCP关闭时一种情况,TCP连接关闭还存在双方同时关闭的情况,如图3所示:
是的,这种情况完全符合我抓包的结果,这种情况是通信的双方都都扮演着客户端与服务端的角色出现的。原来我之前的认知只是片面的,看来学知识还是要去阅读一些经典之作以免造成以偏概全的现象(小声逼逼:网上有些文章抄都抄不全这不是坑人嘛 )。
One comment
大神 我tcpdump 挥手的是这样的
86 8.003195 114.118.30.249 192.168.1.5 TCP 1434 80 → 10066 [ACK] Seq=2761 Ack=432 Win=15744 Len=1380 [TCP segment of a reassembled PDU]
87 8.004030 114.118.30.249 192.168.1.5 HTTP 652 HTTP/1.1 200 OK (PNG)[Malformed Packet]
89 8.004737 192.168.1.5 114.118.30.249 TCP 54 10066 → 80 [ACK] Seq=432 Ack=4739 Win=66048 Len=0
122 10.625847 192.168.1.5 114.118.30.249 TCP 54 10066 → 80 [FIN, ACK] Seq=432 Ack=4739 Win=66048 Len=0
123 10.632870 114.118.30.249 192.168.1.5 TCP 54 80 → 10066 [FIN, ACK] Seq=4739 Ack=433 Win=15744 Len=0
124 10.632957 192.168.1.5 114.118.30.249 TCP 54 10066 → 80 [ACK] Seq=433 Ack=4740 Win=66048 Len=0
为啥会只有三次吗
我测了好几次 有时候跟你情况一样,有时候跟别人的一样 有时候跟我上边发的一样 只有3次并不是4次
期望回答下,