简述

我不想一开始直接搬网络描述图来讲三次握手亦或试图用大量专业词汇让你熟悉它,而是想用简单的描述,让大家对三次握手有个大概的印象。用Wireshark抓包工具分析TCP报文中大家比较关注的syn(Synchronize Sequence Numbers 同步序列号)和ack(ACKnowledge Character 确认字符)。

如果你不能简单的解释它,说明你还没有足够理解它

–爱因斯坦

1 什么是TCP三次握手

字面意思就是三次交互,也是三次 「TCP数据包」 的传输。交互的目的是建立连接,让通信双方确认 「对方」

下图简单描述了三次握手的过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XClx9C0G-1640571969989)(https://tuchuang-oss.oss-cn-hangzhou.aliyuncs.com/img/202112231931554.svg)]

有同学问我为什么要回复x+1,这就是协议的魅力所在了。协议本质上就是一种约定,设计tcp的那群大佬们完全可以设计为x+2,这不应该是我们纠结的点

2 为什么要三次握手

tcp是传输层协议,握手的目的是 建立连接 。事实上四次,甚至更多次的握手更能保证通信的建立,但无疑也会增加网络开销。 「三次」 是一个能够保证双方建立连接的最小通讯数。

3 TCP报文构成

下图为Tcp的报文构成,因本文主要讲述三次握手,侧重点也主要放在序列号和确认应答号上,对TCP的报文感兴趣的可以看看思否的这篇文章。下面结合Wireshark,对应这张图浅析一下三次握手。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qaiky8F7-1640571969991)(https://tuchuang-oss.oss-cn-hangzhou.aliyuncs.com/img/202112260036500.svg)]

三次握手也就是三次TCP的报文传输,这里可以注意到序列号和确认应答号都是32位。所以这也解释了ACK和SYN的取值范围是 0 - 2^32 -1 即4,294,967,295。

4 使用Wireshark浅析三次握手中的报文

简单介绍一下wireshark,它是一款优秀的抓包工具。可以抓取经过我们电脑网卡上的网络信息,当然也包括我们今天要抓取的TCP数据包。

以打开百度为例,首先需要确认百度的ip,可以通过ping命令获取:

shishuai@iMac ~ % ping www.baidu.com
PING www.a.shifen.com (180.101.49.12): 56 data bytes
64 bytes from 180.101.49.12: icmp_seq=0 ttl=52 time=11.738 ms
64 bytes from 180.101.49.12: icmp_seq=1 ttl=52 time=12.248 ms
64 bytes from 180.101.49.12: icmp_seq=2 ttl=52 time=11.474 ms

注意这里使用www.baidu.com而不是baidu.com。记录下反馈的ip地址:180.101.49.12。这个ip因人而异,每个地区会有所不同。

打开wireshark界面:

【ps:建议打开前先退出浏览器。】

wireshark 第三次握手成功 wireshark分析三次握手_wireshark 第三次握手成功

左侧对应你的电脑网卡,如果你不知道选择哪个,可以注意右侧的折线图,有波动的就是你在使用的网卡。

因为我们的电脑的网络流量是实时在变的,所以需要在这里过滤出来自www.baidu.com 的流量信息。

wireshark 第三次握手成功 wireshark分析三次握手_网络_02

对应的过滤规则为:

ip.addr == 180.101.49.12 && tcp

注意这里的ip为上一步通过ping命令获取的ip。

wireshark 第三次握手成功 wireshark分析三次握手_wireshark_03

输入后,回车。可以看到下面还是空的流量信息。现在再打开百度首页,关注这里的流量信息,可以发现三次握手的流量包信息已经显示在下方了:

wireshark 第三次握手成功 wireshark分析三次握手_wireshark 第三次握手成功_04

我们双击第一条报文,查看详情:

wireshark 第三次握手成功 wireshark分析三次握手_三次握手_05

wireshark中显示报文格式为16(2^4)进制,即每个字符对应4位,一共8个字符一共占用4 * 8 = 32位。和可以看TCP报文中syn序列号长度是一致的。16进制下的:e2026015即对应十进制的:3791806485

wireshark 第三次握手成功 wireshark分析三次握手_wireshark_06

当然我们也可以查看原始的2进制数据包,32位的长度也会更加直接。只需要在下方空白处右击,选择:‘… as bits 即可。

wireshark 第三次握手成功 wireshark分析三次握手_三次握手_07

接下来我们点击第二次数据包,即第二次握手,也是百度服务器对我们的回复包:

wireshark 第三次握手成功 wireshark分析三次握手_网络_08

可以看到百度回执ack确实为我们第一次握手中的syn+1(3791806485 + 1)。另外自身生成的seq序列为:1559326373,也对应文章一开始放的小红和小蓝的对话图中的第七步:

wireshark 第三次握手成功 wireshark分析三次握手_wireshark 第三次握手成功_09

这里ack即对应响应ACK(y)值,seq对应服务器返回的x值。

接下来看第三次响应,也是客服端对百度的回执包信息:

wireshark 第三次握手成功 wireshark分析三次握手_网络_10

可以看到最后的一次握手中,ack值为第二次握手回执的syn值+1。seq序列为二次握手中服务器回执的ack确认序列号。至此三次握手完成,连接建立完毕,可以开始进行数据的传输。

5 总结

分析数据包虽然是个比较耗时的事情但确实可以加深我们的印象,也可以让抽象的描述具体化。

另外多说一句,虽然分析的过程比较久但tcp的建立时间是非常快的,我们在打开一个网站的瞬间就建立好了。四次挥手同理,有兴趣的话你可以试试用wireshark抓取4次挥手的数据包看看,希望大家共同进步。