TCP 的三次握手
1. TCP 三次握手(Three-Way Handshake)
目的:三次握手的目的是为了在客户端和服务端之间建立可靠的 TCP 连接,确保双方能够同步,并且为数据传输做好准备。
三次握手的过程:
-
第一次握手:SYN
- 客户端 → 服务端:客户端发送一个 SYN(同步)包,表示请求建立连接,并告知服务端客户端的初始序列号(
seq
)。 - 目的:客户端通知服务端自己希望建立连接。
- 客户端 → 服务端:客户端发送一个 SYN(同步)包,表示请求建立连接,并告知服务端客户端的初始序列号(
-
第二次握手:SYN-ACK
- 服务端 → 客户端:服务端收到客户端的 SYN 包后,发送一个 SYN-ACK 包。该包包括服务端的初始序列号,并且确认客户端的 SYN 包(通过确认号
ack
)。 - 目的:服务端响应客户端的连接请求,并将自己的序列号同步给客户端。
- 服务端 → 客户端:服务端收到客户端的 SYN 包后,发送一个 SYN-ACK 包。该包包括服务端的初始序列号,并且确认客户端的 SYN 包(通过确认号
-
第三次握手:ACK
- 客户端 → 服务端:客户端收到服务端的 SYN-ACK 包后,发送一个 ACK 包确认响应,确认号是服务端的序列号 + 1。
- 目的:客户端确认服务端的连接响应,最终建立起双向的可靠连接。
2. TCP 两次握手的潜在问题
如果使用 两次握手(即客户端发送 SYN 包,服务端发送 SYN-ACK 包后连接立即建立),会导致以下问题:
1) 缺少客户端确认:
- 在两次握手中,客户端没有进行最后的确认。虽然服务端已发送了 SYN-ACK 包,表明同意连接,但客户端没有向服务端发送确认信息,导致服务端无法确定客户端是否真的准备好建立连接。
- 客户端可能已经认为连接已建立,但服务端却没有得到最终确认,因此可能还会继续等待客户端的确认包。
2) 历史连接(半开连接)问题:
- 假设在某些情况下,服务端已发送 SYN-ACK 包,并等待客户端的确认。然而,客户端由于网络问题、崩溃或其他原因没有及时发送 ACK 确认包,导致服务端仍然保持“等待确认”状态,无法知道客户端是否成功接收并准备建立连接。
- 此时,服务端仍然认为连接正在进行中,形成了 历史连接 或 半开连接(Half-open Connection)。这种连接没有完全建立,且服务端可能会将其错误地作为有效连接处理,浪费资源。
3) 误连接(连接干扰):
- 网络中可能会存在延迟、丢包等现象,导致一个已经关闭的连接请求(历史连接)再次到达服务端。
- 如果没有三次握手的确认机制,服务端可能会误认为这是一个新的连接请求,从而错误地处理已经关闭的连接,导致连接状态不一致。
3. 三次握手的解决方案与优势
1) 同步序列号与状态确认:
- 三次握手的第三次确认步骤(客户端发送 ACK 包)确保了双方连接状态的同步。客户端通过发送确认包来确认服务端的响应,服务端也确认客户端准备好进行数据传输。
- 这个步骤避免了服务端错误地认为连接已经建立,且确保双方的初始序列号同步。
2) 防止历史连接与半开连接问题:
- 如果客户端未能成功接收到服务端的 SYN-ACK 响应(例如由于客户端崩溃或网络断开),服务端会保持等待状态,直到超时并关闭连接。这种机制避免了历史连接的重现。
- 半开连接问题也得以避免,只有当客户端和服务端都完成了确认后,才认为连接完全建立,避免了资源的浪费。
3) 更强的可靠性:
- 三次握手确保了连接建立过程中每一步都得到确认,避免了中间丢失消息的风险。这样能保证数据传输的可靠性。
- 由于第三次握手的确认,服务端在建立连接后就能确定客户端准备好接收数据,从而避免误操作或不必要的等待。
4. 两次握手与三次握手的比较
特性 | 两次握手 | 三次握手 |
---|---|---|
握手次数 | 两次 | 三次 |
连接建立是否可靠 | 不完全可靠,可能产生“半开连接”或历史连接问题 | 完全可靠,确保双方同步 |
客户端与服务端状态确认 | 客户端未明确确认服务端响应 | 客户端明确确认服务端响应,确保连接完整 |
连接干扰 | 可能出现误连接(历史连接) | 避免了历史连接问题 |
资源浪费 | 可能导致服务端浪费资源,等待无效连接 | 资源得到了有效利用,避免等待无效连接 |
连接是否能完全建立 | 连接可能没有完全建立,客户端和服务端可能对连接状态不一致 | 连接完全建立,双方同步准备好进行数据传输 |
5. 结论
- 两次握手 虽然在理论上看似可以简化连接建立过程,但会引发 历史连接、半开连接 等严重问题,导致连接状态不一致,浪费系统资源。
- 三次握手 通过增加第三次确认包,确保连接完全建立并且双方对连接状态达成一致,从而提供了 可靠性、资源有效使用、避免半开连接 等优点,是保证 TCP 连接可靠性的关键机制。