TCP 连接建立和终止

TCP连接建立 (三次握手)

建立一个 TCP 连接时会发生如下情形:

  • 服务器必须准备好接受外来请求。这通常通过调用 socket 、bind 、listen 这三个函数来完成。我们称之为 被动打开
  • 客户端通过调用 connect 函数发起 主动打开 。这导致客户 TCP 发送一个 SYN 分节,它告诉服务器客户将在连接中发送的数据的初始序列号。通常 SYN 分节不携带数据,其所在 IP 数据报只含有一个 IP 首部、一个 TCP 首部及可能的 TCP 选项。
  • 服务器必须确认 (ACK) 客户的 SYN,同时自己也得发送一个 SYN 分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器在单个分节中发送 SYN 和对客户 SYN 的ACK。
  • 客户必须确认服务器的 SYN。

图示如下:

在这里插入图片描述

TCP 选项

每一个 SYN 都可以有多个 TCP 选项,下面是常用的选项:

  • MSS 选项。

    发送 SYN 的 TCP 一端使用本选项通告对端它的最大分节大小,也就是它在本连接的每个 TCP 分节中愿意接受的最大数据量。发送端 TCP 使用接收端的 MSS 值作为所发送分节的最大大小。

  • 窗口规模选项

    TCP 连接任何一端能够通告对端的最大窗口大小为 65535 ,因为 TCP 首部中相应的字段占 16 位。然而当今因特网上业已普及的高速网络连接或长延迟路径要求有更大的窗口以获取尽可能大的吞吐量。这个新选项指定 TCP 首部中的通告窗口必须扩大位数 (左移 0 ~ 14位)。因此所提供的最大窗口接近 1GB ( 65535 × 2 14 65535 \times 2 ^ {14} 65535×214) 。在一个 TCP 连接上使用窗口规模的前提是它的两个端系统必须都支持这个选项。

  • 时间戳选项

    这个选项对于高速网络连接时必要的,它可以防止由失而复现的分组可能造成的数据破坏。它是一个较新的选项,也以类似于窗口规模选项的方式协商处理。作为网络编程人员,无需考虑此选项。

TCP 连接终止 (四次挥手)

终止一个 TCP 连接时会发生如下情形:

  • 某个应用进程首先调用 close,我们称该端为 ”主动关闭“。该端的 TCP 于是发送一个 FIN 分节,表示数据发送完毕。
  • 接收到这个 FIN 的对端执行 ”被动关闭“。这个 FIN 由 TCP 确认。它的接收也作为一个文件结束符传递给接收端应用程序 (放在已排队等候该应用进程接收的任何其他数据之后) ,因为 FIN 的接收意味着接收端应用进程在相应连接上再无额外数据接收。
  • 一段时间后,接收到这个文件结束符的应用进程调用 close 关闭它的套接字。这导致它的 TCP 也发送一个 FIN。
  • 接收到这个最终 FIN 的原发送端 TCP 确认这个 FIN 。

既然每一方向都需要一个 FIN 和 ACK ,因此通常需要 4 个分节。但是某些情况下,步骤一的 FIN 会随同数据一起发送;步骤二三发送的分节都出自执行被动关闭的一端,有可能会被合并为一个分节。

如图所示:

在这里插入图片描述

当套接字被关闭时,其所在端 TCP 各自发送一个 FIN,这是由应用进程调用 close 而发生的,不过需要认识到,当一个 Unix 进程无论自愿地 (调用 exit 或从 main 函数返回) 还是非自愿地 (收到一个终止本程序的信号) 终止时,所有打开的描述符都将被关闭,这也导致仍然打开的任何 TCP 连接上也发出一 FIN。

TCP 转换图

TCP 涉及连接建立和连接终止的操作可以使用 状态转换图 来说明。

TCP 为一个连接定义了 11 种状态,并且 TCP 规则规定如何基于当前状态及在该状态下所接收的分节从一个状态转换为另一个状态。

如图所示:

在这里插入图片描述

接下来解释一下该图:

当某个应用进程在 CLOSED 状态下,如果执行主动打开,TCP 将发送一个 SYN,且新的状态为 SYN_SENT,如果接着接收到一个带有 ACK 的 SYN ,TCP 发送一个 ACK,此时新的状态为 ESTABLISHED。

当某个应用进程在 CLOSED 状态下,首先执行被动打开,成为新的状态 LISTEN。接收到一个 SYN,TCP 发送一个带有 ACK 的 SYN ,此时新的状态为 SYN_RECD,紧接着接收到一个 ACK,此时新的状态为 ESTABLISHED。

当某个应用进程在 ESTABLISHED 状态下,如果执行主动关闭,TCP 将发送一个 FIN ,此时新的状态为 FIN_WAIT1,如果此时接收到一个 FIN 并且 TCP 发送一个 ACK,则进入状态 CLOSING。如果此时接收到一个 ACK,则新的状态为 FIN_WAIT2,然后接收到一个 FIN 同时 TCP 发送一个 ACK,则新的状态为 TIME_WAIT。等待若干时间后,进入状态 CLOSED。

当某个应用进程在 ESTABLISHED 状态下,如果执行被动关闭,TCP 将接收到一个 FIN 同时发送一个 ACK,此时新的状态为 CLOSE_WAIT ,然后发送一个 FIN ,此时新的状态为 LAST_ACK,然后接收到一个 ACK,此时新的状态为 CLOSED。

注意:该图中标注了两个特殊的转换——同时关闭和同时打开。这里并没有进行解释。

TIME_WAIT 状态

从 TCP 状态转换图中可以看到,当应用进程处于FIN_WAIT2 状态时,接收一个 FIN 后,首先会进入 TIME_WAIT 状态,然后经过一段时间,才会进入 CLOSED 状态。那么这段时间是多少?为什么要有这样一个状态?

这段时间为最长分节生命期 (MSL) 的两倍,有时候称为 2MSL。而且任何 TCP 实现都必须为 MSL 指定一个值。文档建议时间为 2分钟。

MSL 是任何 IP 数据报能够在因特网中存活的最长时间。我们也知道这个时间是有极限的 (每一个 IP 数据报都有一个最大跳数字段,用于控制路由转发次数,如果最大跳数递减为 0 ,则路由器不再转发此数据报)。因此具有最大跳数的数据报在分组中的存在时间不可能超过 MSL。

有一种情况值得我们注意:IP 数据报可能会 ”迷途“,因为路由异常。

TIME_WAIT 状态存在的两个理由:

  • 可靠地实现 TCP 全双工连接的终止

    假设在 TIME_WAIT 状态下发送的 ACK 丢失,则服务器需要重新发送 FIN 给客户,这其中的耗时为 $ < 2MSL$ ,如果没有这个状态,客户端由于关闭就无法处理服务器发来的 FIN 请求,从而造成服务器方面出错。

  • 允许老的重复分节在网络中消逝

    我们假定一种情景:电脑 A 的 1500 端口和电脑 B 的 21 端口之间有一个 TCP 连接。现在关闭这个连接,然后重新建立一个两者之间的连接。由于两个连接的信息都相同,因此必须防止来自某个连接的老的重复分节出现在新的连接中,从而造成错误。对于此例假设电脑 A 关闭连接时 TIME_WAIT 状态发送的 ACK 丢失,那么电脑 B 一定会重新发送 FIN 。同时假设 电脑 A、B 新建立的连接已经建成,此时接收到 FIN 会造成关闭连接。

    为解决这一问题,TCP 规定不给处于 TIME_WAIT 状态的连接建立新的连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值