技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTNET

“三次握手,四次挥手”你真的懂吗?

所属馆藏
NET Protocol
文件格式
Markdown
原始路径
NET Protocol/10-“三次握手,四次挥手”你真的懂吗?
本文目录14 个章节
  1. 一、什么是“三次握手,四次挥手”
  2. 二、TCP 服务模型
  3. 三、TCP 头部
  4. 四、TCP 状态转换
  5. 五、为什么是“三次握手”
  6. 六、为什么通常是“四次挥手”
  7. 七、三次握手和四次挥手的报文细节
  8. 八、ISN:初始序列号
  9. 九、TCP 序列号回绕
  10. 十、SYN Flood 攻击
  11. 十一、连接队列
  12. 十二、相关命令
  13. 十三、Redis 抓包实例分析
  14. 十四、小结

“三次握手,四次挥手”你真的懂吗?

Category(分类): NET Protocol
Status: 未知

本文主要介绍 TCP 连接建立、数据传输和连接关闭的基本过程,并结合 Linux 连接队列和 Redis 抓包示例进行说明。

文中使用“三次握手”和“四次挥手”描述最常见的过程。实际 TCP 实现还可能出现 SYN 携带数据、ACK 与 FIN 合并、同时关闭以及 SYN Cookie 等情况,因此报文数量并不绝对固定。

一、什么是“三次握手,四次挥手”

TCP 是一种面向连接、可靠的字节流协议,通常用于单播通信。在发送数据前,通信双方必须先建立连接。这里的“连接”并不是物理线路,而是通信双方在内存中维护的一组状态信息,例如本地和远端的 IP 地址、端口号、序列号、确认号、窗口等。这些信息通常保存在 TCP 控制块(TCB)中。

TCP 可以看成一种字节流服务。IP 层可能出现丢包、重复、乱序和数据损坏等情况,TCP 通过序列号、确认号、校验和以及重传机制,为上层应用提供可靠、有序的字节流:

  • 序列号用于标识字节位置,帮助 TCP 检测重复和乱序;
  • 累积确认用于告知发送方已经连续收到的字节范围;
  • 校验和用于检测报文损坏;
  • 超时重传、快速重传等机制用于恢复丢失的数据。

TCP 采用三次握手建立连接,通常采用四次挥手关闭连接。建立连接时,双方需要同步初始序列号(ISN);关闭连接时,两个方向的数据流需要分别结束。

二、TCP 服务模型

2.1 TCP 连接和四元组

一个 TCP 连接通常由以下四元组唯一标识:

源 IP、源端口、目的 IP、目的端口

例如:

192.168.1.10:53000 -> 192.168.1.20:6379

TCP 连接通常可以分为三个阶段:

  1. 连接建立;
  2. 数据传输;
  3. 连接关闭。

2.2 全双工和字节流

TCP 是全双工协议。连接建立后,两个方向都可以独立地发送和接收数据。应用程序可以选择双向通信,也可以只使用其中一个方向。

TCP 不保留应用层的消息边界。例如,应用程序连续调用两次 send(),接收方可能一次 recv() 读到两次发送的数据,也可能分多次读到。因此,应用层协议需要自己设计消息边界,例如固定长度、分隔符或长度字段。

2.3 累积确认

当 TCP 接收到另一端的数据时,通常会发送确认,但确认可能因为延迟确认策略而稍后发送。TCP 的 ACK 通常是累积的:确认号为 N,表示序列号小于 N 的数据已经按序接收,接收方下一步期望收到序列号为 N 的字节。

例如:

ACK = 1001

表示序列号 01000 的字节已经按序收到,接收方期待的下一个字节是 1001

累积确认的好处是,即使某一个 ACK 丢失,后续 ACK 也可能覆盖之前已经确认的范围。

2.4 序列号和乱序处理

IP 协议本身不负责消除重复,也不保证报文按照发送顺序到达。TCP 使用序列号识别数据位置,可以丢弃重复报文,并将乱序到达的数据暂存在接收缓冲区中。

TCP 是字节流协议,不会将乱序数据直接交给应用程序。接收方通常要等缺失的小序列号数据到达后,才能把连续的数据交付给上层。

三、TCP 头部

TCP 头部结构

TCP 头部中的源端口和目的端口用于确定通信双方的应用进程。序列号表示当前报文段中第一个数据字节的序列号;确认号表示发送方期望接收的下一个序列号。确认号字段只有在 ACK 标志位有效时才有意义。

3.1 序列号、确认号和控制位

当建立一个新连接时,客户端发送的第一个 SYN 报文段会携带本端的初始序列号 ISN。如果 SYN 的序列号为 x,那么后续数据通常从 x + 1 开始。SYN 会消耗一个序列号;ACK 本身不携带数据,也不消耗序列号。

FIN 同样会消耗一个序列号。更准确地说,TCP 的报文段长度由数据长度加上 SYN 和 FIN 所占的序列空间组成。

常见控制位如下:

  • ACK:确认号字段有效;
  • RST:立即重置连接,常见的 connection reset by peer 与此有关;
  • SYN:同步序列号,用于建立连接;
  • FIN:发送方没有更多数据需要发送;
  • PSH:提示接收方尽快将数据交给应用程序;
  • URG:紧急指针字段有效;
  • ECE/CWR:与 ECN 拥塞通知有关。

3.2 头部长度

TCP 头部中的数据偏移(Data Offset)以 32 位字为单位,也就是以 4 字节为单位。该字段占 4 位,取值范围为 5~15,因此:

  • 最小 TCP 头部长度:5 × 4 = 20 字节;
  • 最大 TCP 头部长度:15 × 4 = 60 字节。

可选项为空时,TCP 头部通常为 20 字节;使用 MSS、时间戳、窗口扩大等选项时,头部会变长。

在最常见的 TCP 建连和关闭过程中,SYN、ACK、FIN 报文通常只携带 TCP 头部和选项、不携带应用数据。但这不是绝对规则,例如 TCP Fast Open 可以让 SYN 携带数据,FIN 也可以与最后一段数据一起发送。

四、TCP 状态转换

TCP 的建立、传输和关闭会经历不同状态,例如 LISTENSYN-SENTSYN-RECEIVEDESTABLISHEDFIN-WAIT-1FIN-WAIT-2CLOSE-WAITLAST-ACKTIME-WAIT

TCP 状态转换图

几个常见状态的含义如下:

  • LISTEN:服务器等待连接请求;
  • SYN-SENT:主动发起连接后,等待对方响应;
  • SYN-RECEIVED:收到 SYN 并发送 SYN-ACK,等待客户端确认;
  • ESTABLISHED:连接已建立,可以传输数据;
  • FIN-WAIT-1:本端已经发送 FIN,等待 ACK 或对端 FIN;
  • FIN-WAIT-2:本端 FIN 已被确认,等待对端 FIN;
  • CLOSE-WAIT:收到对端 FIN,等待本地应用关闭;
  • LAST-ACK:本端 FIN 已发送,等待最后的 ACK;
  • TIME-WAIT:主动关闭的一方等待一段时间,避免旧报文影响后续连接。

五、为什么是“三次握手”

5.1 三次握手的目的

客户端和服务端通信前要先建立连接。三次握手的主要目的包括:

  1. 确认双方都能发送和接收 TCP 报文;
  2. 交换并确认双方的初始序列号;
  3. 协商 MSS、窗口扩大、SACK、时间戳等 TCP 选项;
  4. 让双方进入 ESTABLISHED 状态。

“三次握手可以确认双方收发能力正常”是便于理解的概括。它验证的是 TCP 报文在两个方向上的可达性和序列号同步,并不等价于应用进程一定正常或网络路径绝对可靠。

5.2 三次握手的过程

假设客户端的初始序列号为 x,服务端的初始序列号为 y

三次握手与收发能力

  1. 第一次握手:客户端发送 SYN
    客户端 -> 服务端:SYN,Seq = x
    

    服务端收到后可以确认:客户端的发送能力正常,服务端的接收能力正常。
  2. 第二次握手:服务端发送 SYN-ACK
    服务端 -> 客户端:SYN + ACK,Seq = y,Ack = x + 1
    

    服务端发送自己的 SYN,同时确认收到了客户端的 SYN。客户端收到后可以确认:服务端能够接收客户端的报文,也能够向客户端发送报文;客户端自己的接收能力也正常。
  3. 第三次握手:客户端发送 ACK
    客户端 -> 服务端:ACK,Seq = x + 1,Ack = y + 1
    

    服务端收到这个 ACK 后可以确认:客户端已经收到服务端的 SYN-ACK,服务端的发送能力和客户端的接收能力均正常。至此,双方完成初始序列号同步,通常进入 ESTABLISHED 状态。

三次握手序列号

5.3 为什么不能只握手两次

如果只有两次握手:

客户端 -> 服务端:SYN
服务端 -> 客户端:SYN + ACK

服务端还没有收到客户端对第二个报文的确认,因此无法确定客户端是否真的收到了自己的 SYN-ACK。第三次 ACK 正是用来让服务端确认客户端已经收到第二次握手的响应。

因此,三次握手不是简单地“多发一个包”,而是完成双方序列号同步和双向可达性确认所需的最小流程。

六、为什么通常是“四次挥手”

TCP 连接是全双工的,两个方向的数据流可以独立关闭。当一方不再发送数据时,它可以发送 FIN,但这只表示“我不再发送”,并不代表它不能继续接收数据。

假设客户端先关闭连接,典型过程如下:

四次挥手过程

  1. 客户端发送 FIN,表示客户端没有更多数据要发送;
  2. 服务端发送 ACK,确认收到客户端的 FIN。此时客户端不能再发送数据,但仍然可以接收服务端的数据;
  3. 服务端应用程序处理完剩余数据后,服务端发送 FIN;
  4. 客户端发送 ACK,确认收到服务端的 FIN。

用序列号表示:

客户端 -> 服务端:FIN,Seq = u
服务端 -> 客户端:ACK,Ack = u + 1
服务端 -> 客户端:FIN,Seq = v,Ack = u + 1
客户端 -> 服务端:ACK,Ack = v + 1

6.1 为什么 FIN 通常不能像 SYN-ACK 一样一次完成

服务端收到客户端的 FIN 时,只能知道客户端不再发送数据了,但服务端应用程序可能还有数据没有发送完。服务端是否发送 FIN,要由服务端应用程序决定,因此服务端通常先发送 ACK,稍后再发送 FIN。

这就是建立连接常见为三次握手,而关闭连接常见为四次挥手的主要原因:

  • 建立连接时,服务端的 SYN 和 ACK 通常可以放在一个报文中;
  • 关闭连接时,ACK 可以立即发送,但 FIN 往往要等应用程序确认没有更多数据后再发送。

6.2 四次挥手并不是绝对固定四个报文

“四次挥手”是最常见的讲法,但实际报文数量可能变化:

  • 如果服务端已经准备好关闭,ACK 和 FIN 可以合并发送;
  • 如果双方同时发送 FIN,可能进入 CLOSING 状态;
  • FIN 可以与最后一段应用数据一起发送。

主动关闭的一方通常会进入 TIME-WAIT。该状态用于确保对端收到最后一个 ACK,并避免旧连接中的延迟报文影响后续使用相同四元组建立的新连接。

七、三次握手和四次挥手的报文细节

7.1 三次握手

  1. 客户端发送一个 SYN 段,并指明客户端的初始序列号 ISN(c)
  2. 服务端发送自己的 SYN 段作为应答,并指明 ISN(s)。为了确认客户端的 SYN,确认号为 ISN(c) + 1
  3. 客户端为了确认服务端的 SYN,将 ISN(s) + 1 作为 ACK 的值。

每发送一个 SYN,都会消耗一个序列号。如果 SYN 丢失,TCP 会根据重传机制重新发送。

7.2 四次挥手

假设客户端当前序列号为 K,服务端当前序列号为 L

  1. 客户端发送 FIN,序列号为 K,并携带对服务端最近数据的 ACK;
  2. 服务端将 K + 1 作为 ACK,表示已经收到客户端的 FIN;
  3. 服务端应用程序处理完数据后,发送 FIN,序列号为 L,确认号为 K + 1
  4. 客户端发送 ACK,确认号为 L + 1

八、ISN:初始序列号

三次握手的一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便双方知道接下来如何根据序列号组织和确认数据。

早期规范中常用下面的形式描述 ISN 生成算法:

ISN = M + F(localip, localport, remoteip, remoteport, secretkey)

其中:

  • M 是随时间单调增加的计时器,经典规范中约每 4 微秒增加一次;
  • F() 是基于连接四元组和秘密信息计算的伪随机函数;
  • secretkey 用于避免外部攻击者根据已经观察到的序列号推算其他连接的 ISN。

这个公式用于解释设计思想,不应直接当成所有操作系统的实际源代码。现代系统会结合内核版本、随机密钥和其他安全策略生成 ISN。

ISN 的设计同时考虑了两个问题:

  1. 避免旧连接的延迟报文被误认为属于新连接;
  2. 降低攻击者猜测序列号并伪造 TCP 报文的概率。

良好的 ISN 不能替代 TLS、IPsec 或 TCP-AO 等真正的身份认证机制。

九、TCP 序列号回绕

TCP 序列号字段只有 32 位,序列号空间为 02^32 - 1,超过最大值后会从 0 重新开始。这叫作序列号回绕(sequence wraparound)。

序列号回绕不是因为随机 ISN 超过 2^31 - 1,而是因为 32 位序列号空间按 2^32 取模循环。TCP 不能简单使用无符号整数的大小比较,而要使用序列号空间中的相对顺序。通常只有在两个序列号相距小于 2^31 时,这种比较才是有意义的。

Linux 内核中常见的比较思路如下:

/*
 * The next routines deal with comparing 32 bit unsigned ints
 * and worry about wraparound (automatic with unsigned arithmetic).
 */
static inline int before(__u32 seq1, __u32 seq2)
{
    return (__s32)(seq1 - seq2) < 0;
}

#define after(seq2, seq1) before(seq1, seq2)

__u32 表示 32 位无符号整数,__s32 表示 32 位有符号整数。通过将相减结果解释为有符号数,可以在一定范围内正确判断回绕后的先后关系。

为了便于理解,可以用 8 位序列号做一个类比。假设序列号从 0255 循环:

seq1 = 255
seq2 = 1

255 - 1 = 254

如果将 8 位结果 254 解释为有符号 8 位整数,它等于 -2。这说明在序列号回绕的语义下,255 可以被判断为位于 1 之前。真实 TCP 使用的是 32 位序列号,并且必须遵守半序列号空间的限制,不能直接照搬这个 8 位例子进行任意比较。

十、SYN Flood 攻击

最基本的 DoS(Denial of Service,拒绝服务)攻击之一,是利用大量请求占用服务端资源,使合法用户无法得到及时响应。SYN Flood 就是针对 TCP 建连过程的一类 DoS 攻击。

10.1 攻击原理

攻击者向服务器端口发送大量 SYN 报文。服务器收到 SYN 后,通常需要保存一个待完成连接的状态,向客户端回复 SYN-ACK,并进入 SYN-RECEIVED 状态,等待客户端最后的 ACK。

大量半连接会占用连接队列、定时器和内存资源。如果攻击者伪造源 IP,使服务器回复的 SYN-ACK 无法到达真正的发送者,服务器还需要等待重传超时,资源会被占用更久。

不同操作系统的具体实现不同。Linux 通常会使用较轻量的 request_sock 保存半连接请求,并可以通过 SYN Cookie 等机制减少为每个请求分配完整 TCB 的需求,因此不应把某个固定的 TCB 字节数当成普遍结论。

10.2 常见防护方法

无效连接的超时释放

系统可以通过重传次数和超时机制清理长时间没有完成的半连接。这种方法简单,但对攻击连接和正常连接一视同仁,不能单独解决大规模 SYN Flood。

SYN Cache

系统只在专用的数据结构中保存完成握手所必需的少量信息,收到正确 ACK 后再创建完整连接控制块。这样可以降低半连接状态的内存开销。

SYN Cookie 不为每一个半连接保存完整的服务器端状态,而是将部分必要信息编码进服务端发送的初始序列号中。收到客户端 ACK 后,服务端重新计算并验证该 ACK,验证通过后再创建连接。

SYN Cookie 可以显著降低半连接队列压力,但会受到序列号空间和 TCP 选项空间的限制,具体行为取决于实现。

SYN Proxy 防火墙

SYN Proxy 通常会在客户端和后端服务器之间分别建立两个 TCP 连接:

  1. 防火墙先与客户端完成 TCP 握手;
  2. 防火墙验证客户端的 ACK 后,再向内部服务器发起新的 SYN;
  3. 后续数据由防火墙在两条连接之间转发。

这种方式可以将大量不完整连接挡在后端服务器之外,但防火墙需要维护两条连接的状态,并可能需要处理两端的序列号转换。

十一、连接队列

在外部连接请求到达后、被服务程序通过 accept() 取走前,连接可能处于 SYN-RECEIVEDESTABLISHED 状态。Linux 服务端通常可以从两个队列的角度理解这个过程:

TCP 连接队列

  1. 半连接队列:保存处于 SYN-RECEIVED 状态、等待客户端最终 ACK 的请求;
  2. 全连接队列(accept 队列):保存已经完成握手、等待应用程序 accept() 的连接。

这两个队列的具体实现和参数会随操作系统、内核版本以及 SYN Cookie 是否启用而变化。

11.1 半连接队列

Linux 中,tcp_max_syn_backlog 表示每个监听 socket 能够记住的、尚未收到客户端确认的连接请求数量。请求通常处于 SYN-RECEIVED 状态。

服务器收到 SYN 后,会创建轻量级的请求状态并回复 SYN-ACK;当收到客户端 ACK 后,连接才会进入已完成连接队列。

半连接队列

tcp_synack_retries 控制服务端 SYN-ACK 的重传次数。不同内核、初始 RTO 和配置会影响实际等待时间,因此不应简单地把重试时间固定为 31 秒。可以通过系统参数查看当前配置:

sysctl net.ipv4.tcp_synack_retries
sysctl net.ipv4.tcp_max_syn_backlog

11.2 全连接队列

当服务端收到第三次握手的 ACK 后,连接会进入监听 socket 的完成队列,等待应用程序调用 accept()

全连接队列

如果完成队列满了,Linux 的行为受到 tcp_abort_on_overflow 等参数影响:

  • 默认情况下,内核可能暂时丢弃 ACK,并在稍后重传 SYN-ACK,等待客户端再次确认;
  • 如果启用 tcp_abort_on_overflow,内核可能直接发送 RST,让客户端收到 connection reset by peer
  • 客户端也可能因为长时间收不到有效响应而出现连接超时。

相关参数可以这样查看:

sysctl net.ipv4.tcp_abort_on_overflow
cat /proc/sys/net/core/somaxconn

服务端并不是简单地“重传 SYN 和 ACK”,而是重传一个 SYN-ACK 报文,目标是客户端,而不是服务端自己。

十二、相关命令

查看 TCP 统计信息:

netstat -s | grep -Ei 'listen|overflow'

部分系统也可以使用:

ss -s
ss -lnt

ss -lnt 中常见字段含义如下:

State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
LISTEN  0       128     0.0.0.0:6379        0.0.0.0:*

对于监听 socket,Recv-QSend-Q 的具体含义取决于系统版本;通常可以将 Send-Q 理解为监听队列上限,将 Recv-Q 理解为当前等待应用程序处理的连接数量。

十三、Redis 抓包实例分析

下面保留原文中的 Redis 抓包示例,用于分析 TCP 三次握手和 Redis PING/PONG 数据。

13.1 抓取 6379 端口数据

在 dev 机器上部署 Redis 服务,端口号为 6379。在 dev2 机器上使用 redis-cli 访问 dev:6379

使用 tcpdump 抓包:

tcpdump -i any -nn -s 0 -w /tmp/a.cap 'port 6379'

参数说明:

  • -i any:监听所有可用网卡,具体接口也可以替换为 eth0 等;
  • -nn:不解析主机名和端口服务名;
  • -s 0:使用当前 tcpdump/libpcap 版本的默认快照长度,现代版本通常足以抓取完整报文;
  • -w:将原始数据包写入文件;
  • 'port 6379':只捕获与 6379 端口相关的报文。

-S 与抓取长度无关,它用于让 tcpdump 显示绝对 TCP 序列号:

tcpdump -r /tmp/a.cap -nn -S

读取并分析捕获文件:

tcpdump -r /tmp/a.cap -nn -A -x | vim -

其中,-A 以 ASCII 形式显示部分数据,-x 以十六进制形式显示数据。-n-nn 功能有重叠,实际使用一个 -nn 即可。

13.2 IP 数据包和 TCP 数据

抓到的是 IP 数据包。对于 IPv4,IP 数据包通常由 IPv4 头部和 IP 数据部分组成;当上层协议是 TCP 时,IP 数据部分就是 TCP 头部加 TCP 数据。

IP 数据包格式

IPv4 头部最小为 20 字节,存在选项时会变长。IPv6 的基本头部长度和格式不同,不能直接套用下面的 IPv4 抓包解析。

IPv4 头部格式

TCP 头部同样是 20 字节固定部分加可选项部分:

TCP 头部详细格式

TCP 选项位于 TCP 头部末尾,常见选项包括 MSS、SACK、时间戳和窗口扩大:

TCP 选项格式

13.3 三次握手分析

原始抓包中的第一段类似下面这样:

10:55:45.662077 IP dev2.39070 > dev.6379: Flags [S], seq 4133153791, win 29200, options [mss 1460,sackOK,TS val 2959270704 ecr 0,nop,wscale 7], length 0
        0x0000:  4500 003c 08cf 4000 3606 14a5 0ab3 b561
        0x0010:  0a60 5cd4 989e 18eb f65a ebff 0000 0000
        0x0020:  a002 7210 872f 0000 0204 05b4 0402 080a
        0x0030:  b062 e330 0000 0000 0103 0307

第一个包是 dev2 向 dev 发送的 SYN 请求:

dev2 -> dev
SYN = 1
Seq(c) = 4133153791

第二个包是服务端响应:

SYN = 1
ACK = 4133153792
Seq(s) = 4264776963

服务端的 ACK = Seq(c) + 1,表示已经收到客户端的 SYN。服务端自己的 SYN 序列号为 4264776963

第三个包是客户端确认:

Seq = 4133153792
ACK = 4264776964

这里的 ACK = Seq(s) + 1,说明客户端已经收到服务端的 SYN-ACK。至此,TCP 三次握手完成,双方可以开始传输应用数据。

需要注意,tcpdump 默认可能显示相对序列号。使用 -S 才会显示绝对序列号;原始十六进制数据中看到的是实际的 32 位序列号。

13.4 Redis PING 数据分析

第四个包是客户端向服务端发送 Redis PING 请求:

10:55:48.090073 IP dev2.39070 > dev.6379: Flags [P.], seq 1:15, ack 1, win 229, options [nop,nop,TS val 2959273132 ecr 3132256230], length 14
        0x0000:  4500 0042 08d1 4000 3606 149d 0ab3 b561
        0x0010:  0a60 5cd4 989e 18eb f65a ec00 fe33 5504
        0x0020:  8018 00e5 4b5f 0000 0101 080a b062 ecac
        0x0030:  bab2 6fe6 2a31 0d0a 2434 0d0a 7069 6e67
        0x0040:  0d0a

TCP 首部长度为 32 字节,其中可选项长度为 12 字节。IP 报文总长度为 66 字节,IPv4 头部为 20 字节,因此 TCP 数据部分长度为:

66 - 20 - 32 = 14 字节

数据部分为:

2a31 0d0a 2434 0d0a 7069 6e67 0d0a

对应的 ASCII 内容为:

0x2a31         -> *1
0x0d0a         -> \r\n
0x2434         -> $4
0x0d0a         -> \r\n
0x7069 0x6e67  -> ping
0x0d0a         -> \r\n

这正是 Redis 协议中的:

*1\r\n$4\r\nping\r\n

第四个包的 TCP 数据序列号为 4133153792,因此 tcpdump 使用相对序列号显示为 seq 1:15

13.5 ACK 和 PONG 数据分析

第五个包是客户端对 PING 数据的确认:

Seq = 4264776964
ACK = 4133153806

其中:

4133153806 = 4133153792 + 14

说明服务端已经可以继续从 4133153806 开始接收客户端数据。

第六个包是服务端返回的 PONG:

Seq = 4264776964
ACK = 4133153806

TCP 数据长度为 7 字节,数据内容为:

2b50 4f4e 470d 0a

翻译为:

+PONG\r\n

至此,Redis 客户端和服务端的 PING/PONG 数据交换分析完成。TCP 三次握手已经在前三个包中完成。如果完整抓包中还有第七个纯 ACK,应将其作为服务端 PONG 的确认单独说明,不能把它再次称为三次握手。

十四、小结

TCP 三次握手和四次挥手可以概括为:

  • 三次握手:交换初始序列号,确认双向可达性,建立连接;
  • 数据传输:使用序列号、ACK、窗口和重传机制提供可靠的字节流;
  • 四次挥手:两个方向分别关闭,通常需要 FIN、ACK、FIN、ACK 四个报文;
  • 序列号:用于按序交付、重复检测、丢包恢复和连接安全;
  • SYN Flood:利用半连接状态消耗服务端资源,可通过 SYN Cookie、SYN Proxy、队列调优和流量清洗等方式缓解。

相关资料:

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS