从 Wireshark 看一次请求的过程

— By BingqiChen

从大学有网络课程起就知道有三次握手这回事,但对其中到底发生了什么一直懵懵懂懂,今天打算借助 Wireshark 这一著名的网络数据包分析软件重现一下握手过程。

TCP 头部格式释义

字段对应关系及释义:

TCP头部格式

三次握手

关于 Wireshark

Wireshark

在 Wireshark 中左边实线(图中21 - 28、133 - 134、427 - 428)连起来的一段可以视为为同一次会话内发生的各个阶段,不过图中的是简单顺利的一次会话过程,没有失败重传、分片传输等其他情况。

另外:

文中7001为服务器所在端口号。

三次握手之一

第21个网络包:客户端发送第一个网络包,在头部写入发送方、接收方端口号(用来找到目标套接字),设置客户端初始序号为0, SYN 控制位为1,等待服务器确认,由于此时客户端还未接收过网络包,所以 ACK 控制位为0。

三次握手之二

第22个网络包:服务器收到网络包,同样返回一个响应包,在TCP头部写入发送方、接收方端口号(此时对服务器来说是发送方)、服务端初始序号0, SYN 控制位1,另外还要设置 ACK 控制位为1,表示已收到有效网络包;除此之外可以注意到 ACK号 也被置为1了,就是上文提到的 SYN 控制位占用的一个确认号。

三次握手之三

第23个网络包:客户端收到网络包,发现 SYN 控制位为1,表示连接成功,同时发送一个 ACK 控制位设置为1的网络包给服务器,告知服务器刚才的响应包已收到,这里可以发现序号变为1,那是因为服务器返回的响应包中确认了客户端发送的 SYN 控制位为1,所以序号需要 +1;在服务器收到后三次握手就全部完成了,后面就可以开始收发数据了。

三次握手示意图

后面的[TCP Window Update]是用来窗口更新的,这里不做阐述。

收发数据

客户端发起请求

第25个网络包:客户端发起了一个 HTTP 页面请求,TCP详细信息如下:

No.25

可以看到这个网络包已经不单单是控制信息的传输,开始包含数据,并且数据占用621字节,同时 Wireshark 已经机智在计算下一个客户端发送的包序号了, 621…...

服务器发送确认包

然后服务器告知客户端已收到该请求,响应第26个网络包:

No.26

ACK号 = 前一次的 ACK号 + 本次收到的数据字节数 = 1 + 620 = 621;

序号保持不变,因为本次只是发送控制信息,并没有发送数据。

Tips:在 WireShark 选中某个网络包,如上图No.26,结果No.25前面出现了一个对勾,可以看作是No.26对No.25的消息确认。

服务器发送内容响应请求

在第27个网络包中,服务器针对HTTP请求返回页面内容:

No.27

可以看到这个网络包的数据大小为4152字节,这之后理论上在客户端应该会返回一个 ACK号 为4153的确认包。

客户端发送确认包

No.28

在第28个网络包中,序号就如前面 Wireshark 计算的等于621,ACK号的计算和第26个网络包相似,不再赘述。

关闭连接

在结束最后一个网络包的传输后,再过一段时间(上图中大概5秒),如没有数据往来Web服务器就会关闭连接,至于为什么要延时,大概是为了短时间内如果有后续数据交换,可以减少重新创建套接字建立连接的开销吧。

关闭连接握手之一

服务器生成包含断连控制信息 FIN 的TCP头部发送给客户端。

关闭连接握手之二

客户端告知服务器已收到断连信号 FIN , 因为收到的 FIN 占用一个确认号,所以回复的 ACK号 = 4153 + 1 = 4154。

关闭连接握手之三

客户端在读取所有缓冲区的数据后,也会向服务器发送一个 FIN 为1的网络包。

关闭连接握手之四

服务器同理返回 ACK号 确认收到 FIN 控制信息。

这就是断连操作的四次握手。

关闭连接示意图

附测试数据

测试数据下载链接,过滤规则 tcp.port == 7001