0
点赞
收藏
分享

微信扫一扫

【TEST】负载/性能测试工具 Grafana K6 (Docker 版)

目录

一. 四次挥手

(1)过程描述

(2)为什么是四次挥手?

二、相关问题

1. 第一次挥手丢失了,会发生什么?

2. 第二次挥手丢失了,会发生什么?

补充:close 函数 和 shutdown 函数的不同

3. 第三次挥手丢失了,会发生什么?

4. 第四次挥手丢失了,会发生什么?

5. 为什么需要 TIME_WAIT 状态?

(1)防止历史连接中的数据,被后面相同四元组的连接错误的接收

(2)保证「被动关闭连接」的一方,能被正确的关闭

6. 什么情况会出现三次挥手?

什么是 TCP 延迟确认机制?


一. 四次挥手

(1)过程描述

  • ① 客户端 打算 关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
  • ② 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSE_WAIT 状态。
  • ③ 客户端 收到 服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
  • ④ 等待 服务端 处理完数据后,也向 客户端 发送 FIN 报文,之后 服务端 进入 LAST_ACK 状态。
  • ⑤ 客户端 收到 服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态。
  • ⑥ 服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此 服务端已经 完成连接的关 闭。
  • ⑦ 客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此 客户端 也完成 连接的关闭。

(2)为什么是四次挥手?

二、相关问题

1. 第一次挥手丢失了,会发生什么?

        当客户端(主动关闭方)调用 close 函数后,就会向服务端发送 FIN 报文,试图与服务端断开连接,此时客户端的连接进入到 FIN_WAIT_1状态。正常情况下,如果 能 及时 收到服务端(被动 关闭方)的 ACK,则会很快变为 FIN_WAIT_2 状态。

        如果 第一次挥手 丢失了,那么 客户端迟迟 收不到 被动方的 ACK 的话,也就会 触发 超时重传机制,重传 FIN 报文,重发次数由 tcp_orphan_retries 参数 控制。当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后,就不再发送 FIN 报文,则会在等待一段时间(时间为上一次超时时间的 2 倍),如果 还是没能 收到 第二次挥手,那么 直接进入到 close 状态

2. 第二次挥手丢失了,会发生什么?

        当服务端 收到客户端的 第一次挥手后,就会先回一个 ACK 确认 报文,此时 服务端 的 连接进入到 CLOSE_WAIT 状态

        ACK 报文是不会重传的,所以 如果 服务端的 第二次挥手 丢失了,客户端 就会 触发超时重传机制,重传 FIN 报文,直到 收到 服务端的 第二次挥手,或者 达到最大的 重传次数。

补充:close 函数 和 shutdown 函数的不同

        对于 close 函数关闭的 连接,由于 无法再 发送 和 接收数据,所以 FIN_WAIT_2 状态 不可以 持续太久,而 tcp_fin_timeout 控制了 这个状态下 连接的 持续时长,默认值是 60 秒。

3. 第三次挥手丢失了,会发生什么?

        当 服务端(被动关闭方)收到 客户端(主动关闭方)的 FIN 报文后,内核会 自动回复 ACK,同时 连接处于 CLOSE_WAIT 状态,顾名思义,它表示 等待 应用进程 调用 close 函数 关闭连接。此时,内核 是 没有权利 替代 进程 关闭连接,必须 由进程 主动 调用 close 函数来 触发 服务端 发送 FIN 报文。

        服务端 处于 CLOSE_WAIT 状态时,调用了 close 函数,内核 就会 发出 FIN 报文,同时 连接进入LAST_ACK 状态,等待 客户端 返回 ACK 来 确认连接 关闭。如果 迟迟 收不到这个 ACK,服务端就会重发 FIN 报文,重发次数 仍然 由 tcp_orphan_retries 参数 控制,这与 客户端 重发 FIN 报文的 重传次数 控制方式是 一样的。

4. 第四次挥手丢失了,会发生什么?

        当 客户端 收到服务端的 第三次挥手的 FIN 报文后,就会 回 ACK 报文,也就是 第四次挥手,此时 客户端 连接 进入 TIME_WAIT 状态。

        在 Linux 系统,TIME_WAIT 状态 会持续 2MSL 后才会 进入 关闭状态。然后,服务端(被动关闭方)没有收到 ACK 报文前,还是处于 LAST_ACK 状态。如果 第四次挥手 的 ACK 报文 没有 到达服务端,服务端 就会 重发 FIN 报文,重发次数 仍然由 tcp_orphan_retries 参数 控制。

5. 为什么需要 TIME_WAIT 状态?

(1)防止历史连接中的数据,被后面相同四元组的连接错误的接收

        序列号和初始化 序列号 并不是 无限递增的,会 发生 回绕为 初始值的 情况,这意味着 无法 根据序列号来 判断 新老数据。

        为了 防止历史 连接中的 数据,被 后面 相同四元组的 连接错误的 接收,因此 TCP 设计了 TIME_WAIT 状态,状态 会 持续 2MSL 时长,这个 时间 足以让 两个方向上的 数据包都 被丢弃,使得 原来 连接的 数据包 在网络中 都 自然消失,再 出现的 数据包 一定都是 新建立 连接 所产生的。

(2)保证「被动关闭连接」的一方,能被正确的关闭

        假设 客户端 没有 TIME_WAIT 状态,而是在 发完 最后一次 回 ACK 报文就 直接进入 CLOSE 状态,如果该 ACK 报文 丢失了,服务端 则 重传的 FIN 报文,而这时 客户端 已经 进入到 关闭状态了,在 收到服务端 重传的 FIN 报文后,就会回 RST 报文。

        服务端 收到 这个 RST 并将其 解释为一个 错误(Connection reset by peer),这对于 一个 可靠的协议 来说 不是一个 优雅的 终止方式。为了 防止这种 情况出现,客户端 必须 等待足够长的 时间,确保 服务端 能够收到 ACK,如果 服务端 没有 收到 ACK,那么 就会触发 TCP 重传机制,服务端会 重新 发送一个 FIN,这样 一去一来 刚好 两个 MSL 的时间。

6. 什么情况会出现三次挥手?

        当 被动 关闭方(上图的 服务端)在 TCP 挥手过程中,「没有数据要发送」并且「开启了 TCP 延迟确认机制」,那么 第二 和 第三次 挥手 就会 合并传输,这样就 出现了 三次挥手。(TCP 延迟确认机 制 默认开启)


什么是 TCP 延迟确认机制?

        当 发送 没有携带 数据的 ACK,它的 网络效率 也是 很低的,因为 它也有 40 个字节的 IP 头 和TCP 头,但却 没有 携带 数据报文(浪费)。

举报

相关推荐

0 条评论