TCP的三次握手和四次挥手过程依赖于TCP报文段头中的标志字段和数据序号来建立和终止可靠的连接。让我们详细分析每个阶段这些字段的变化:
一、三次握手 (Establishing Connection)
三次握手旨在建立一个可靠的、全双工的通信连接。 三个阶段如下:
-
阶段1:客户端发送SYN报文
- 标志字段: SYN = 1 (同步序列号),表示这是一个连接请求。其他标志位(ACK, FIN, RST, PSH, URG)都为0.
- 数据序号: 客户端选择一个初始序列号ISNClient (Initial Sequence Number),这个数字是任意的,但通常是一个随机数。 这个序号会写入数据序号字段。 这个序号代表了客户端发送的第一个字节的数据。 报文中没有实际数据传输,所以数据部分为空。
-
阶段2:服务器发送SYN/ACK报文
- 标志字段: SYN = 1 (同步序列号),ACK = 1 (确认序列号),表示接受连接请求并发送确认。 其他标志位为0.
- 数据序号: 服务器选择一个初始序列号ISNServer。 这个序号同样是任意的,并且独立于客户端的ISN。
- 确认序号 (ACK): ACK字段的值为ISNClient + 1。 这表示服务器已经收到客户端发送的SYN报文,并确认了客户端的序列号。
-
阶段3:客户端发送ACK报文
- 标志字段: ACK = 1 (确认序列号),其他标志位为0. SYN标志位为0,因为连接请求已经发送过了。
- 数据序号: ISNClient + 1。这是客户端维持数据序号的延续。
- 确认序号 (ACK): ISNServer + 1。 客户端确认收到服务器的SYN/ACK报文。
总结三次握手:
阶段 | 发送方 | 接收方 | SYN | ACK | 数据序号 | 确认序号 |
---|---|---|---|---|---|---|
1 | 客户端 | 服务器 | 1 | 0 | ISNClient | - |
2 | 服务器 | 客户端 | 1 | 1 | ISNServer | ISNClient + 1 |
3 | 客户端 | 服务器 | 0 | 1 | ISNClient + 1 | ISNServer + 1 |
二、四次挥手 (Terminating Connection)
四次挥手用于优雅地终止一个TCP连接。 双方都需要分别发送FIN报文来关闭各自方向的数据流。
-
阶段1:客户端发送FIN报文
- 标志字段: FIN = 1 (结束标志),表示客户端不再发送数据。 其他标志位为0.
- 数据序号: Seq = ISNClient + x,其中x是客户端自三次握手以来发送的数据字节数。
-
阶段2:服务器发送ACK报文
- 标志字段: ACK = 1,其他标志位为0.
- 数据序号: Seq = ISNServer + y,其中y是服务器自三次握手以来发送的数据字节数。
- 确认序号 (ACK): SeqClient + 1 (客户端FIN报文的序号+1)
-
阶段3:服务器发送FIN报文
- 标志字段: FIN = 1,其他标志位为0.
- 数据序号: Seq = ISNServer + z,其中z是服务器自上一个ACK报文以来发送的数据字节数。
-
阶段4:客户端发送ACK报文
- 标志字段: ACK = 1,其他标志位为0.
- 数据序号: Seq = ISNClient + w,其中w是客户端自上一个ACK报文以来发送的数据字节数。
- 确认序号 (ACK): SeqServer + 1 (服务器FIN报文的序号+1)
总结四次挥手:
阶段 | 发送方 | 接收方 | FIN | ACK | 数据序号 | 确认序号 |
---|---|---|---|---|---|---|
1 | 客户端 | 服务器 | 1 | 0 | ISNClient + x | - |
2 | 服务器 | 客户端 | 0 | 1 | ISNServer + y | ISNClient + x + 1 |
3 | 服务器 | 客户端 | 1 | 0 | ISNServer + z | - |
4 | 客户端 | 服务器 | 0 | 1 | ISNClient + w | ISNServer + z + 1 |
重要说明: x
, y
, z
, w
表示在各个阶段中传输的数据量,这些数值会根据实际的数据传输情况而变化。 数据序号是累加的,每个报文的序号是基于之前发送的数据字节数累加得到的。 确认序号总是指向下一个期望接收的字节。 理解数据序号和确认序号的累加机制对于理解TCP的可靠性至关重要。
TCP三次握手和四次挥手虽然看起来简单,但一些细节容易出错,导致理解偏差。以下是一些常见的易错点:
三次握手易错点:
-
ISN (初始序列号) 的理解: 许多人误以为ISN是固定的或可预测的。实际上,ISN是随机选择的,目的是为了防止旧的连接请求被重放攻击。 理解ISN的随机性对于理解TCP的安全性至关重要。
-
ACK 确认序号的含义: ACK确认序号并非指最后接收到的字节的序号,而是指下一个期望接收的字节的序号。 这很容易混淆,要牢记这个关键区别。
-
SYN和ACK标志位同时出现: 在服务器的第二个报文中,SYN和ACK同时出现,这表示服务器既接受了连接请求(ACK),又发送了自己的连接请求(SYN)。 很多人会误以为这是两个独立的报文。
-
三次握手的目的: 三次握手不仅仅是建立连接,它也用于同步双方的序列号,为后续可靠的数据传输奠定基础。
四次挥手易错点:
-
为什么需要四次挥手?: 很多人不明白为什么关闭连接需要四个步骤而不是三个。 这是因为TCP连接是全双工的,每个方向都需要单独关闭。 客户端关闭发送方向的数据流后,服务器需要发送ACK确认,然后服务器再关闭接收方向的数据流,客户端也需要发送ACK确认。
-
TIME_WAIT状态: 客户端在最后一次ACK发送后,会进入TIME_WAIT状态,持续2MSL (Maximum Segment Lifetime)。 这个状态非常重要,它确保之前发送的报文能够可靠地到达,并防止旧的连接请求被重用。 很多人不理解TIME_WAIT状态的意义和作用,容易忽略它的存在。
-
LAST-ACK: 服务器在发送FIN报文后,并不一定立即关闭连接,而是在收到客户端的ACK之后才会进入CLOSED状态。 这个状态的延迟是必要的,以确保客户端的ACK能够被正确接收。
-
半关闭状态: 在四次挥手过程中,可能存在一个连接处于半关闭状态。 例如,客户端发送FIN报文后,服务器仍然可以发送数据给客户端,直到服务器也发送FIN报文。
总的易错点总结:
- 序号和确认序号的区别与计算: 理解数据序号和确认序号是如何累加的,以及确认序号指向下一个期望接收的字节,这是理解TCP可靠性的核心。
- 标志位的含义和组合: 准确理解SYN、ACK、FIN等标志位的含义,以及它们在不同报文中的组合,对理解握手和挥手的过程至关重要。
- TCP状态机: 理解TCP连接的各个状态(例如LISTEN、SYN_SENT、ESTABLISHED、CLOSE_WAIT、TIME_WAIT等)及其转换,可以帮助更好地理解整个过程。
让我们通过一些例子来加深对TCP三次握手和四次挥手的理解,并重点说明易错点。 这些例子会简化一些细节,例如最大报文段生存时间(MSL)的影响,以突出核心概念。
例题一:三次握手中的序号和确认序号
假设客户端的初始序列号(ISN)是1000,服务器的ISN是2000。 请写出三次握手过程中每个报文的序列号和确认序号。
解答:
阶段 | 发送方 | 接收方 | SYN | ACK | 数据序号 (Seq) | 确认序号 (Ack) |
---|---|---|---|---|---|---|
1 | 客户端 | 服务器 | 1 | 0 | 1000 | - |
2 | 服务器 | 客户端 | 1 | 1 | 2000 | 1001 |
3 | 客户端 | 服务器 | 0 | 1 | 1001 | 2001 |
易错点分析: 很多同学在第二步容易写错确认序号,记住确认序号是下一个期望接收的字节序号,而不是最后接收到的字节序号。
例题二:四次挥手中的序号和确认序号 (无数据传输)
假设在例题一建立的连接后,没有数据传输,客户端发起关闭连接。 请写出四次挥手过程中每个报文的序列号和确认序号。
解答:
阶段 | 发送方 | 接收方 | FIN | ACK | 数据序号 (Seq) | 确认序号 (Ack) |
---|---|---|---|---|---|---|
1 | 客户端 | 服务器 | 1 | 0 | 1001 | - |
2 | 服务器 | 客户端 | 0 | 1 | 2001 | 1002 |
3 | 服务器 | 客户端 | 1 | 0 | 2001 | - |
4 | 客户端 | 服务器 | 0 | 1 | 1002 | 2002 |
易错点分析: 很多同学容易混淆FIN和ACK标志位的位置和作用。 记住FIN表示“我这边的数据发送完毕”,ACK表示“我已收到你的报文”。 而且,序列号在每一次发送FIN或者数据后都会递增。
例题三:四次挥手中的序号和确认序号 (有数据传输)
假设在例题一建立的连接后,客户端发送了包含100字节数据的报文,然后发起关闭连接。 服务器也发送了包含50字节数据的报文,然后关闭连接。 请尝试写出四次挥手过程中每个报文的序列号和确认序号 (这题比较难,需要仔细思考序号的累加)。 (为了简化,我们忽略数据包分片情况,假定所有数据都在一个包里传输)。
解答: 这题比较复杂,需要考虑数据传输对序号的影响。 假设客户端发送数据的序号起始为1001,服务器发送数据的序号起始为2001。
阶段 | 发送方 | 接收方 | FIN | ACK | 数据序号 (Seq) | 确认序号 (Ack) | 数据长度 |
---|---|---|---|---|---|---|---|
1 | 客户端 | 服务器 | 1 | 0 | 1101 | - | 0 |
2 | 服务器 | 客户端 | 0 | 1 | 2051 | 1102 | 50 |
3 | 服务器 | 客户端 | 1 | 0 | 2051 | - | 0 |
4 | 客户端 | 服务器 | 0 | 1 | 1102 | 2052 | 0 |
易错点分析: 这题的难点在于需要正确计算每个阶段的序列号和确认序号,包括数据传输对序列号的影响。 序列号是累加的,确认序号始终指向下一个期望接收到的字节。
TCP三次握手和四次挥手的理论基础主要来源于TCP/IP协议族,更具体地说,是TCP协议规范本身。 并没有单一的论文或书籍可以作为其理论来源的唯一权威,而是多个RFC文档以及众多网络书籍共同构成了其理论基础。
以下是几个重要的方面和相关的RFC文档以及书籍:
-
RFC 793: Transmission Control Protocol: 这是TCP协议的原始规范文档,其中详细描述了TCP三次握手和四次挥手的过程,以及相关的状态机、序列号、确认号等概念。 它是理解TCP核心机制的最权威来源。 虽然这个RFC文档比较老,但其核心思想仍然是现代TCP实现的基础。
-
RFC 1122: Requirements for Internet Hosts — Communication Layers: 这个RFC文档对Internet主机进行通信层的规范,其中包含了对TCP行为的许多要求,进一步阐明了TCP三次握手的目的和意义,以及对可靠性的要求。
-
RFC 6298: Computing TCP’s Retransmission Timer: 虽然不是直接描述三次握手和四次挥手,但这个RFC文档阐述了TCP重传计时器的计算方法,而这与TCP可靠性密切相关,间接地解释了为什么需要三次握手来建立可靠的连接。
-
各种计算机网络教材: 像《计算机网络》(谢希仁著)、《计算机网络:自顶向下方法》(Kurose & Ross著)等经典教材中,都会对TCP三次握手和四次挥手进行详细的讲解和分析,并结合图示和例子帮助读者理解。这些教材通常会参考RFC文档,并对其中的概念进行更深入的解释和补充,更适合入门学习。
需要注意的是,RFC文档通常比较技术性和细节性,对于初学者来说可能比较难以理解。 教材则更注重知识的系统性和可读性,能够更好地帮助初学者理解TCP三次握手和四次挥手的原理和应用。 两者结合学习,才能获得更全面的理解。
除了上述文档和书籍,还有大量的学术论文和研究文章探讨TCP协议的优化和改进,但这些通常都建立在RFC 793等基础规范之上。 因此,理解RFC 793等核心规范文档是掌握TCP三次握手和四次挥手理论基础的关键。 而教材则提供了更易于理解的学习路径。