• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

TCP的三报文建立连接和四报文释放连接

武飞扬头像
单程车票
帮助2

前言

在讲解三报文握手和四报文挥手前,先回顾一下 TCP 报文段的首部格式:

学新通

  • 序列号 seq:在 TCP 连接中传送的字节流中的每一个字节都按顺序编号,在 TCP 建立连接时第一个字节的编号由计算机随机生成,而报文段的序列号指的是该报文段的第一个字节的编号。序列号范围在 0 ~ 232-1(也就是说当序号增加到 232-1 后下一个序号又回到 0)。序列号是用于标记报文段的顺序,解决网络包乱序问题。
  • 确认号 ack:指期待收到对方下一个报文段的序列号,即当前报文段最后一个字节的序号 1 就是确认号(也可以理解为当前报文段的序列号 数据长度),用于表示这个确认号之前的数据都被正确接收,解决丢包问题。
  • 确认 ACK:当 ACK = 1 时确认字段才有效,TCP 规定在建立连接时所有传送的报文段都必须将 ACK 置为 1。
  • 复位 RST:当 RST = 1 时表明 TCP 连接中出现严重差错,必须释放连接。
  • 同步 SYN:在连接建立时用来同步序号,当 SYN = 1表示这是一个连接请求或连接接收请求,此时会对该报文段的序列号字段进行初始化(由本地随机生成)。
  • 终止 FIN:当 FIN = 1 时表示此报文段的发送方的数据已经发送完毕要求释放连接。

了解了上面 TCP 的首部格式字段概念后,下面将讲解 TCP 的三报文建立连接和四报文释放连接。


TCP 的三报文建立连接

与 UDP 不同,TCP 是面向连接的,所以在使用 TCP 之前需要先建立连接,下面来看看 TCP 是如何建立连接的以及为什么要三报文建立连接。

三报文建立连接过程图(这里引用计算机网络微课堂的过程图,有兴趣了解计算机网络的推荐观看计算机网络微课堂):

学新通

三报文建立连接过程:

  1. 建立连接之前,两端的 TCP 进程处于 CLOSED 关闭状态。服务器进程首先创建传输控制块,并进入 LISTEN 监听状态,被动等待 TCP 客户端进程的连接请求。客户端进程也会创建传输控制块,并主动打开连接。
  2. 客户端进程向服务器进程发送 TCP 连接请求报文段,并进入 SYN-SENT 同步已发送状态。该报文段首部中:
    • SYN 同步位置为 1,表示这是一个 TCP 连接请求报文段。
    • seq 序列号设置为初始值 x(计算机随机生成),作为 TCP 客户端进程的初始序列号。
  3. 服务器进程收到客户端进程的连接请求报文段后,若同意建立连接,则向客户端进程发送 TCP 连接请求确认报文段,并进入 SYN-RCVD 同步已接受状态。该报文段首部中:
    • SYN 同步位置为 1 且 ACK 确认位置为 1,表示这是一个 TCP 连接请求确认报文段。
    • seq 序列号设置为初始值 y(计算机随机生成),作为 TCP 服务器进程的初始序列号。
    • ack 确认号设置为 x 1,这是对 TCP 客户端进程所选择的初始序列号的确认。
  4. 客户端进程收到服务器进程的连接请求确认报文段后,向服务器进程发送一个普通的 TCP 确认报文段,并进入 ESTABLISHED 连接已建立状态。该报文段首部中:
    • ACK 确认位置为 1,表示这是一个普通的 TCP 确认报文段。
    • seq 序列号置为 x 1,这是因为客户端进程的第一个 TCP 报文段序列号为 x,所以客户端进程发送的第二个报文段序列号设置为 x 1。
    • ack 确认号设置为 y 1,这是对 TCP 服务器进程所选择的初始序列号的确认。
  5. 服务器进程收到客户端进程的普通确认报文段后,进入 ESTABLISHED 连接已建立状态。此时,两端的 TCP 进程都已进入连接已建立状态,可以进行可靠的数据传输。

为什么三报文中第二报文的确认号与第三报文的序列号和确认号变化都是加 1 ?

需要说明的是 SYN 被设置为 1 的报文段是不能携带数据的,这是因为 SYN 报文属于特殊的 TCP 报文只在建立连接时使用。虽然 SYN 报文不携带数据,但是 TCP 将该报文视为 1 字节的数据,也就是说同样要消耗一个序列号。

这就可以说明为什么服务器进程发送的第二报文的确认号 ack = x 1,这表示对客户端进程发送的第一报文(序列号 seq = x)的确认,并且服务器进程期望下次收到的报文的是客户端进程发送序列号为 seq = x 1 的报文段,加 1 的原因是因为 SYN 报文只消耗一个序列号。

客户端进程发送的第三报文的序列号 seq = x 1 自然是客户端进程上一次发送报文(第一报文)的序列号 1,而第三报文的确认号 ack = y 1 同样也就是表明对服务器进程发送的第二报文(seq = y)的确认,并且客户端进程期望下次收到的报文的是服务器进程发送序列号为 seq = y 1 的报文段。

为什么不是两报文建立连接呢?

先说原因:两报文建立连接无法防止历史(已失效)连接的建立,可能造成两端之间的资源浪费

再说为什么,引用一张计算机网络微课堂的图:

学新通

采用两报文建立连接,即服务器进程收到客户端进程的连接请求报文段后,服务器进程就进入连接已建立状态;客户端进程收到服务器进程的连接请求确认报文段后,客户端进程也进入连接已建立状态。

那么当出现上图这样的情况时,客户端进程第一次发送的连接请求报文段因为网络等原因被滞留阻塞,客户端进程超时重发新的连接请求报文段,此时在两报文建立连接的前提下,服务器进程收到新的连接请求报文段后便进入连接已建立状态,并发送连接请求确认报文段,使得客户端进程也进入连接已建立状态,并完成数据传输然后释放连接。之后历史(已失效)连接请求报文段才抵达服务器进程,此时服务器进程收到后便进入连接已建立状态,并发送连接请求确认报文段给客户端进程。但是客户端进程此时并没有发出新的建立连接请求,便不会向服务器进程发送报文段,导致服务器进程一直等待(直到保活计时器到时关闭连接),白白浪费资源

采用三报文建立连接,出现上述情况时,服务器进程收到历史(已失效)连接请求报文段时,进入的是同步已接收状态,此时并没有建立连接,而后向客户端进程发送连接请求确认报文段时,由于客户端进程无响应,服务器进程超时重传多次后,便会断开连接。这样就可以防止历史(已失效)连接的建立,避免造成资源浪费

至于为什么不采用四报文建立连接?显而易见,三报文建立连接已经可以保证可靠建立连接了,就没必要使用更多的通信次数。


TCP 的四报文释放连接

有 TCP 建立连接,自然就会有 TCP 释放连接,下面来看看 TCP 是如何释放连接的以及为什么要四报文释放连接。

注意:与建立连接不同的是 TCP 任何一方都可以在数据传送结束后发出连接释放的通知

四报文释放连接过程图(这里引用计算机网络微课堂的过程图):

学新通

这里以客户端进程发出的连接释放通知展示四报文释放连接过程:

  1. 释放前,TCP 两端进程处于 ESTABLISHED 连接已建立状态。客户端进程主动关闭 TCP 连接,向服务器进程发出 TCP 连接释放报文段,并进入 FIN-WAIT-1 终止等待1状态。该报文段首部中:
    • FIN 终止位置为 1 并且 ACK 确认位置为 1,表示这是一个 TCP 连接释放报文段,并且对之前收到的报文段进行确认。
    • seq 序列号置为 u,这里以 u 代表 TCP 客户端进程之前已发送过的数据的最后一个字节的序号加 1。
    • ack 确认号置为 v,这里以 v 代表 TCP 客户端进程之前已收到过的数据的最后一个字节的序号加 1。
  2. 服务器进程收到客户端进程发送的连接释放报文段后,会发送一个普通的 TCP 确认报文段,并进入 CLOSE-WAIT 关闭等待状态。该报文段首部中:
    • ACK 确认位置为 1,表示这是一个普通的 TCP 确认报文段。
    • seq 序列号置为 v,这里与上面的连接释放报文段中的确认号匹配(因为这就是客户端进程期望收到的序列号)。这里的 v 代表 TCP 服务器进程之前发送过的数据的最后一个字节的序号加 1。
    • ack 确认号置为 u 1,这是对上面的连接释放报文段的确认,并期望客户端进程下一次发送的报文段的序列号为 u 1。
  3. 客户端进程收到服务器进程的确认报文段后,进入 FIN-WAIT-2 终止等待2状态。至此,从 TCP 客户端进程到 TCP 服务器进程这个方向的连接就释放了,这时的 TCP 连接属于半关闭状态。也就是说 TCP 客户端进程已经没有数据要发送了,但服务器进程可能还有数据要发送。
  4. 当服务器进程的应用进程也没有数据要发送时,应用进程通知服务器进程释放连接。即服务器进程向客户端进程发送 TCP 连接释放报文段,并进入 LAST-ACK 最终确认状态。该报文段首部中:
    • FIN 终止位置为 1 并且 ACK 确认位置为 1,表示这是一个 TCP 连接释放报文段,并且对之前收到的报文段进行确认。
    • seq 序列号置为 w,这里的 w 代表半关闭状态下服务器进程已发送的数据的最后一个字节的序号加 1。
    • ack 确认号置为 u 1,这是对之前收到的客户端进程发送的 TCP 连接释放报文段的重复确认。
  5. 客户端进程收到服务器进程的连接释放报文段后,会发送一个普通的 TCP 确认报文段,并进入 TIME-WAIT 时间等待状态。该报文段首部中:
    • ACK 确认位置为 1,表示这是一个普通的 TCP 确认报文段。
    • seq 序列号置为 u 1,这里 u 1 是客户端进程上一次发送的序列号 u 加上数据长度 1(这里数据长度是 1,是因为 FIN 报文与 SYN 报文类似,同样不携带数据,但是消耗一个序列号)。
    • ack 确认号置为 w 1,这是对服务器进程的连接释放报文段的确认。
  6. 服务器进程收到客户端进程的确认报文段后,服务器进程就进入 CLOSE 关闭状态,客户端进程经过 2MSL 后也进入 CLOSE 关闭状态

为什么需要四报文释放连接?

为什么建立连接只需要三报文,而释放连接却需要四报文呢,查看三报文建立连接和四报文释放连接的过程图,可以看到三报文建立连接时服务器进程收到客户端进程的连接建立报文段后,直接将 ACK 确认报文和 SYN 同步报文合并一起发送,而四报文释放连接时服务器进程先回复 ACK 确认报文段,等待服务器进程数据传输完毕后,才发送 FIN 终止报文,这就是比三报文多出一报文的地方。那么为什么释放连接不直接将 ACK 确认报文和 FIN 终止报文合并发送呢?

这是因为客户端进程主动释放连接时,客户端进程向服务器进程发送连接释放报文段,此时只是表示客户端进程没有数据要发送,但是客户端进程仍然可以接收数据。服务器进程收到客户端进程的连接释放报文段后回复确认报文,表示服务器进程知晓客户端没有数据要发送了,关闭了从客户端进程到服务器进程的连接。但是重点在于此时服务器进程可能还有数据需要发送给客户端进程,所以服务器进程还不能发送 FIN 报文关闭从服务器进程到客户端进程的连接。只有等服务器进程的所有数据传输完成后,才会发送 FIN 报文关闭连接。到这里才算是 TCP 两端释放连接。这就是为什么需要四报文释放连接的原因。

为什么需要 TIME-WAIT 时间等待状态?

需要说明的是只有主动发起释放连接的一方,才会有 TIME-WAIT 时间等待状态

先说原因:TIME-WAIT 时间等待状态可以保证被动关闭连接的一方能正确被关闭

再说为什么,引入计算机网络微课堂的一张图:

学新通

从上图中可以看到,如果没有 TIME-WAIT 时间等待状态,当客户端进程发送的确认报文段(第四报文)在网络中丢失时,此时客户端进程已经进入 CLOSE 关闭状态,服务器进程因为接收不到客户端进程的确认报文段,会重发 FIN 报文(连接释放报文段),但是此时由于客户端进程处于关闭状态,所以客户端进程接收不到该报文段,导致服务器进程无法进入 CLOSE 关闭状态。

所以可以看出有 TIME-WAIT 时间等待状态是为了确保 TCP 服务器进程可以收到最后的客户端进程确认报文段而进入 CLOSE 关闭状态。

此外补充说明为什么 TIME-WAIT 等待时间为 2MSL,MSL 指的是报文最大生存时间,即任何报文在网络上存在的最长时间,超过这个时间就会被丢弃。而 2MSL 可以保证使本次连接持续时间内所产生的报文段都从网络中消失,也就是说在下一次新的 TCP 连接中,不会出现旧连接中的报文段


这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhbjeaii
系列文章
更多 icon
同类精品
更多 icon
继续加载