0%

计算机网络(三):详解 TCP 三次握手与四次挥手

1. TCP 的传输过程

  • 打开连接 -> 写请求数据 -> 读响应数据 -> 关闭连接

2. TCP 的握手时机

  • HTTP 连接网络的时候会进行 TCP 的三次握手

3. TCP 三次握手的过程

  • 第一次握手

    • 建立连接。客户端发送连接请求报文段,将 SYN 设置为 1、seq 设置为 x;接下来客户端进入 SYN_SENT 状态,等待服务端的确认
  • 第二次握手

    • 服务端收到客户端的 SYN 报文段,对 SYN 报文段进行确认,设置 ACK 为 x+1(seq+1);同时自己还要发送 SYN 请求信息,将 SYN 设置为 1、seq 设置为 y。服务端将上述所有信息放到 SYN+ACK 报文段中,一并发送给客户端,此时服务端进入 SYN_RCVD 状态
  • 第三次握手

    • 客户端收到服务端的 SYN+ACK 报文段;然后将 ACK 设置为 y+1,向服务端发送 ACK 报文段,这个报文段发送完毕后,客户端和服务端都进入 ESTABLISHED (TCP 连接成功)状态,完成 TCP 的三次握手

4. TCP 的挥手时机

  • 客户端和服务端通过三次握建立了 TCP 连接后,开始传送数据,当数据传送完毕、断开连接时就需要进行 TCP 的四次挥手

5. TCP 四次挥手的过程

  • 第一次挥手

    • 客户端设置 seq 和 ACK,向服务端发送一个 FIN 报文段。此时,客户端进入 FIN_WAIT_1 状态,表示客户端没有数据要发送给服务端了
  • 第二次挥手

    • 服务端收到了客户端发送的 FIN 报文段,向客户端回了一个 ACK 报文段
  • 第三次挥手

    • 服务端向客户端发送 FIN 报文段,请求关闭连接,同时服务端进入 LAST_ACK 状态
  • 第四次挥手

    • 客户端收到服务端发送的 FIN 报文段,向服务端发送 ACK 报文段,然后客户端进入 TIME_WAIT 状态。服务端收到客户端的 ACK 报文段以后,就关闭连接。此时,客户端等待 2MSL(2 倍最大报文段生存时间) 后依然没有收到回复,则说明服务端已正常关闭,这样客户端也可以关闭连接了(服务端先关闭,客户端后关闭)

6. TCP 三次握手流程图

7. TCP 四次挥手流程图

8. TCP 三次握手四次挥手过程中各种符号的含义

符合 含义
seq sequence number 序列号,占 4 个字节,它是发送端数据包的初始序号。seq=x 表示发送端数据包的初始序列号为 x,seq=0 表示这是第 0 号帧
ack acknowledge number 确认号,占 4 个字节,它是对这次收到数据包的确认,以及对下次收到数据包的期待。ack=x+1 表示我方到 x 为止的所有数据都已正确收到,且告知对方:我期待你方下次给我发送包的初始序号(seq)是 x+1
ACK Acknowledge field significant 确认序号,占一个比特位,它表示响应。ACK=1 表示确认号(seq)有效,ACK=0 确认号无效
SYN Synchronized sequence numbe 同步序号,它表示建立连接。TCP 规定 SYN=1 时不能携带数据,但要消耗一个序号,因此随机选取一个序列号为 seq=x 的数据包(该数据包里就是一个标记 seq,并没有任何的有效数据)
FIN Final number 结束序号,它表示结束一个 TCP 会话,但对应端口仍处于开放状态准备接收后续数据

9. 为什么 TCP 规定 ISN(Initial Sequence Number, 初始序号) 是随机的

  • 建立连接的起始方是随机选择 ISN 的初始值,所以这个初始值并没有什么特殊的意义
  • 这个初始值必须随机选择,如果重复使用一个初始值的话,服务端在一些特殊情况下会感到不确定,可能会认为这是之前报文段的数据重发
  • 程序都是人写的,从机器的角度来看,不确定性越少越好

10. 为什么需要三次握手而不是两次四次

  • 假设, Client 发出连接请求,但因连接请求报文段丢失而未收到 Server 确认,于是 Client 重传一次连接请求。后来收到了 Server 确认,建立了连接,数据传输完毕后,就释放了连接
  • 但是,很有可能第一次丢失的报文段只是在某些网络结点长时间滞留导致延迟,延迟到连接释放后的某个时间才到达 Server,此时 Server 误以为 Client 又发出一次新的连接请求,于是就向 Client 发出确认报文段,同意建立连接
  • 所以,不采用三次握手,只要 Server 发出确认,就建立新的连接,此时 Client 不理会 Server 的确认且不发送数据,则 Server 一直等待 Client 发送数据,浪费 Server 资源

11. 什么是 DDos 攻击,为什么服务器容易受到 DDos 攻击

  • DDos 全称:Distributed Denial of Service,即:分布式拒绝服务。除了 DDos 攻击,还有最早的 DoS 攻击(拒绝服务)和最新的 DRDos 攻击(分布反射式拒绝服务)
  • DDos 最常用的攻击策略就是使用 SYN-Flood 攻击,即 SYN 洪泛攻击
  • 服务端的资源分配是在二次握手时分配的,而客户端的资源分配是在完成三次握手时分配的,所以服务器容易受到 SYN 洪泛攻击
    • SYN 洪泛攻击就是 Client 在短时间内伪造大量的不存在的 IP 地址,并向 Server 不断的发送 SYN 包,Server 则回复确认包,并等待 Client 确认
    • 由于源地址不存在,因此 Server 需要不断重发直至超时(通常在 30 秒到 2 分钟),这些伪造的 SYN 包将长时间占用未连接队列,导致正常的 SYN 请求因为队列满而放弃,从而引起网络堵塞甚至系统瘫痪

12. 什么是未连接队列

  • 在 TCP 三次握手过程中,服务器维护一个未连接队列
  • 该队列为每个客户端的 SYN 包开设一个条目,该条目表明服务器已收到 SYN 包,并向客户端发出确认,在等待客户端的确认包时,删除该条目,服务器进入 ESTABLISHED 状态

13. TCP 建立连接后数据传输过程包括哪些

  • 超时重传,快速重传,流量控制,拥塞控制

14. 为什么连接的时候是三次握手,关闭的时候是四次

  • 建立连接时,当服务端在 LISTEN 状态下的 SOCKET 收到 SYN 的建立连接请求后,它可以直接发送 SYN+ACK 报文。服务端把 SYN 和 ACK 放到一个报文里,ACK 起应答作用,SYN 起同步作用
  • 关闭连接时,当服务端收到 FIN 报文,它只表示客户端没有数据要发给服务端了,并不意味着服务端所有数据都已经发给客户端了。所以,服务端并不会立即关闭 SOCKET,只能先回复一个 ACK 报文表示客户端的 FIN 报文已收到。只有当服务端所有报文都发送完了,才会发送 FIN 报文给客户端表示能够关闭连接了。所以这里的 ACK 和 FIN 是分两步分开发送的

15. 什么是 2MSL,为什么 Client 在 TIME_WAIT 状态还要等 2MSL 才能返回到 CLOSED 状态

  • 2MSL:

    • MSL 全称:Maximum Segment Lifetime, 即:报文最大生存时间,RFC 793 标准中规定 MSL 为 2 分钟,实际应用中常用的是 30 秒、1 分钟、2 分钟等
    • 2MSL 即两倍的报文最大生存时间
  • 理由:

    • 尽管双方都允许关闭连接了,并且握手的 4 个报文也都协调和发送完成,按道理客户端能够直接回到 CLOSED 状态。但我们必须要假设网络是不可靠的,我们无法保证客户端最后发出的 ACK 一定会被服务端收到,因此服务端处于 LAST_ACK 状态下的 SOCKET 可能会由于长时间未收到客户端的 ACK 报文导致超时重发 FIN 报文给客户端,所以客户端这个 TIME_WAIT 状态的作用就是用来重发可能丢失的 ACK 报文给服务端
    • 报文可能会被混淆,即其他时间的连接可能会被当作本次的连接。当 TCP 连接发送一些物理上的意外情况时,比如网线断开,Linux 上的 TCP 实现会依旧认为当前连接有效,而 windows 则会在一定时间后返回错误信息
-------------------- 本文结束感谢您的阅读 --------------------