实验 24:TCP 的运输连接管理
# 240.实验 24:TCP 的运输连接管理
下面我们来进行一个仿真实验,本仿真实验的目的在于验证 TCP 使用三报文握手来建立连接,使用四报文挥手来释放连接。
我们首先来构建一个非常简单的网络拓扑,只需要一台普通的主机和一台普通的服务器,然后将它们直连即可,选择这里的终端设备,然后拖动一台普通的主机到逻辑工作空间,再拖动一台普通的服务器到逻辑工作空间,选择自动连线方式,将主机和服务器连接起来即可。
接下来给主机和服务器分别配置 IP 地址和地址掩码,点击主机在弹出窗口中选择桌面选项卡,配置的 IP 地址为 192.168.0.1,默认子网掩码 255.255.255.0,不用修改。
再来给服务器配置 IP 地址和地址掩码,点击服务器在弹出窗口中选择桌面选项卡,然后选择 IP 配置的 IP 地址为 192.168.0.2,默认子网掩码 255.255.255.0,不用修改。
下面我们来检查一下物理拓扑以及之前的配置工作是否正常。
点击主机在弹出窗口中选择桌面选项卡,然后选择网页浏览器,这样我们就打开了仿真软件为我们提供的一个简易的网页浏览器,在地址栏中输入服务器的 IP 地址,192.168.0.2,然后点击前往按钮或按下回车键,可以看到主机中的浏览器获取到了服务器中的网页内容,这就表明我们的配置工作都是正常的,可以进行下面的仿真实验了。
对于本仿真实验,我们关心的是 TCP 的连接建立与释放的过程,至于和浏览器相关的 HTTP 协议,HTML 语言等并不是本仿真实验的重点,您只需要知道本仿真实验所要实现的应用功能,在应用层需要使用 HTTP 协议,在运输层需要使用 TCP 协议即可。
接下来我们从实时模式切换到仿真模式,监听 HTTP 协议和 TCP 协议即可,我们再次点击浏览器中的前往按钮,来看看浏览器访问 WEB 服务器内容,TCP 协议在其中所扮演的角色,可以看到主机现在准备发送一个数据包,我们点击该数据包来看看详细情况。由于 HTTP 协议需要使用运输层的 TCP 协议所提供的运输服务,而 TCP 又是面向连接的,也就是在数据传输之前必须首先建立逻辑连接关系,因此主机尝试与服务器建立 TCP 连接。
我们来看看主机运输层的具体处理,设置 TCP 连接状态为同步已发送,然后准备一些协商参数,例如可接受的最大窗口值,使用最大报文段容量 MSS 选项等,发送 TCP 连接请求报文段,也就是这里显示的 SYN 报文段,该报文段首部中的 SYN 标志位被设置为一,首部中的序号字段的值为 0,这是主机位自己选择的初始序号,请注意,这只是仿真软件给出的值,实践当中不一定是 0,而是一个随机值。确认号 ACK 字段的取值为 0,该字段的值对于本报文段而言其实没有意义,因为本报文段并不是一个确认报文段,这里的数据长度 24 是指该 TCP 连接请求报文段的总长度为 24 字节,由于 TCP 连接请求报文段不能携带数据,因此这 24 字节其实就是该报文段的首部长度,TCP 首部有 20 字节的固定部分和最大 40 字节的选项部分构成,因此可知有四字节是选项部分,具体为三字节的最大报文段容量 MSS 选项和一字节的填充,使用一字节填充是为了使 TCP 首部长度能被四字节整除,您也可以点击出站 PDU 详情选项卡,来查看 TCP 封包的详情,我这里就不再赘述了。
当然 TCP 连接请求报文段还要封装成 IP 数据报,IP 数据报还要封装成以太网帧才能进行发送,为了把重点放在 TCP 上,后面我们就不再提及 IP 数据报和以太网帧的封装了:
点击这里的捕获前进按钮进行单步仿真,可以看到主机发送 TCP 连接请求报文段给服务器,点击该报文段。我们来看看服务器的处理情况,服务器收到该报文段后,解析出该报文段是 TCP 连接请求报文段,服务器接受连接请求,进入同步已接收状态:
然后服务器准备给主机发回 TCP 连接请求确认报文段,也就是这里显示的 SYN 加 ACK 报文段,该报文段首部中的 SYN 标志位和 ACK 标志位都被设置为一,序号字段的值为 0,这是服务器为自己选择的初始序号,请注意这只是仿真软件给出的值,实践当中不一定是 0,而是一个随机值。
确认号 ACK 字段的取值为 1,表明这是对 TCP 连接请求报文段的确认,因为报文段的序号为 0,且不携带数据:
关闭弹出窗口,再次点击捕获前进按钮,可以看到服务器发送 TCP 连接请求确认报文段给主机:
点击该报文段。我们来看看主机的处理情况,主机收到该报文段后,解析出该报文段是 TCP 连接请求确认报文段,就要进入连接已建立状态。
然后主机准备给服务器发回一个普通的 TCP 确认报文段,也就是这里显示的 ACK 报文段,该报文段首部中的 ACK 标志位被设置为 1,序号字段的值为 1,这是因为之前主机所发送的不携带数据的 TCP 连接请求报文段使用了序号 0,因此主机现在发送的 TCP 报文段的序号应该为 1,确认号 ACK 字段的值为 1,表明这是对 TCP 连接请求确认报文段的确认,因为报文段的序号为 0,且不携带数据:
再次点击捕获前进按钮,可以看到主机发送普通的 TCP 确认报文段给服务器,点击该报文段,我们来看看服务器的处理情况,服务器收到该报文段后,解析出该报文段是对 TCP 连接请求确认报文段的确认,就要进入连接已建立状态,至此主机和服务器都已进入连接已建立状态,他们可以基于已建立好的 TCP 连接进行数据传输了:
再次点击捕获前进按钮,可以看到主机发送 HTTP 请求报文给服务器,点击该报文可以看到 HTTP 请求报文使用 TCP 报文段来封装,并且报文段首部中的 Push 标志位为一,表明服务器应尽快地将该报文段交付给应用进程,而不再等到整个缓存都填满了,再向上交付。
ACK 标志位为 1,表明该报文段还对之前收到的 TCP 连接请求确认报文段进行了重复确认。
序号字段的值为 1,这是因为主机之前发送的普通 TCP 确认报文段的序号为一,它不携带数据也不消耗序号。
确认号 ACK 字段的值为 1,这是对之前收到的 TCP 连接请求确认报文段的确认,因为报文段的序号为 0 且不携带数据,长度为 100,表明该 TCP 报文段总长为 100 字节。
服务器对收到的 HTTP 请求做出响应,构建出 HTTP 响应报文,使用 TCP 报文段来封装该 HTTP 响应报文,报文段首部中的序号字段的取值为 1,这是因为服务器之前发送的 TCP 连接请求确认报文段要消耗掉一个序号,当时选的初始序号为 0,且不携带数据,那么现在服务器发送的 TCP 报文段的序号就应该取 1,确认号 ACK 字段的取值为 101,这是对之前收到的封装有 HTTP 请求报文的 TCP 报文段的确认,因为报文段的序号为 1,长度为 100,因此确认号 ACK 应当取值为 101,数据长度 471,表明该 TCP 报文段总长为 471 个字节:
再次点击捕获前进按钮,可以看到服务器发送 HTTP 响应报文给主机,主机收到该报文后进行解析,就可以显示出具体的网页内容了。现在主机和服务器间的应用层传输结束了:
主机要发起运输层 TCP 连接的释放,可以看到主机准备发送一个 TCP 报文段,点击该报文段查看其详细内容,主机设置 TCP 连接状态为终止等待,并准备发送 TCP 连接释放报文段,也就是这里所显示的 FIN 加 ACK 报文段,该报文段首部中的 FIN 标志位和 ACK 标志位都设置为 1,序号字段的取值为 101,这是因为主机之前发送的封装有 HTTP 请求报文的 TCP 报文段的序号为一,且长度为 100。
确认号 ACK 字段的取值为 472,这是对所收到的封装有 HTTP 响应报文的 TCP 报文段的确认,因为报文段的序号为 1,长度为 471。
再次点击捕获前进按钮,可以看到主机发送 TCP 连接释放报文段给服务器,点击该报文段。我们来看服务器的处理。
服务器解析该 TCP 报文段,发现这是 TCP 连接释放报文段,于是进入关闭等待状态。由于服务器此时也没有数据要发给主机了,于是又进入最后确认状态,请注意这与我们理论课讲解时稍有不同,理论课讲解时所举例子是处于关闭等待状态的服务器,还有数据要发给主机:
处于最后确认状态的服务器,还要给主机发送 TCP 连接释放报文段,也就是这里所显示的 FIN 加 ACK 报文段,该报文段首部中的 FIN 标志位和 ACK 标志位都设置为 1,序号字段的取值为 472,这是因为服务器之前发送的封装有 HTTP 响应报文的 TCP 报文段的序号为 1,长度为 471,确认号 ACK 为 102,这是对所收到的 TCP 连接释放报文段的确认,因为报文段的序号为 101,且不携带数据:
再次点击捕获前进按钮,可以看到服务器发送 TCP 连接释放报文段给主机,点击该报文段。我们来看主机的处理,主机解析带 TCP 报文段,发现这是 TCP 连接释放报文段,于是进入正在关闭状态,这相当于我们理论课中介绍的时间等待状态,也就是要等待一段时间才进入关闭状态:
处于正在关闭状态的主机,还要给服务器发送一个普通的 TCP 确认报文段,该报文段首部中的 ACK 标志位设置为一 序号字段的取值为 102,这是因为主机之前所发送的 TCP 连接释放报文段的序号为 101 且不携带数据,那么现在主机发送的 TCP 报文段的序号就应当为 102,确认号 ACK 为 472,这是对所收到的 TCP 连接释放报文段的确认,因为报文段的序号为 472,且不携带数据:
再次点击捕获按钮,可以看到主机发送普通的 TCP 确认报文段给服务器,点击该报文段,我们来看看服务器的处理,服务器解析该 TCP 确认报文段就要进入了关闭状态,一段时间后主机中的 TCP 也会进入关闭状态,那时 TCP 连接释放过程才彻底结束:
TCP 连接建立和释放的过程还是比较复杂的,尤其是三豹纹握手,四豹纹挥手所使用的 7 个报文段,其首部中的同步标志位 SYN,终止标志位 FIN,确认标志位 ACK,序号字段,确认号字段的取值,以及这些报文段是否可以携带数据,非常容易弄错,建议在仿真实验的过程中把它们记录下来,以便搞清楚它们之间的关系。
最后还需要提醒您注意的是在我们的教学过程中,发现有的同学认为通过这里就可以看出 TCP 三报文握手建立连接,四报文挥手释放连接:
但实际上这是不对的,这里的同一个 TCP 报文段可能出现在不同行,用来表示该报文段当前在哪个设备上,或该报文段是由哪个设备发往哪个设备,对于本地 TCP 释放连接,实际上只使用了 3 个报文段,而不是这里所显示的 4 个报文段。