TCP 三次握手(Three-Way Handshake)是为了在 客户端 和 服务器 之间建立一个可靠的连接,并且确保双方都准备好进行数据传输。三次握手的目的是为了确保数据传输的可靠性、顺序性以及连接的双方都能够正常发送和接收数据。
为什么需要三次握手?
-
确保双方都准备好进行连接:
- TCP 是一个 面向连接 的协议。在通信之前,客户端和服务器需要先确认彼此的存在,并且都准备好接收和发送数据。三次握手通过交换控制消息来确保连接双方都能正常启动并准备好进行数据传输。
-
确保双方都能够处理数据包的顺序:
- 在建立连接时,TCP 需要交换 序列号(Sequence Number)。序列号用于确保数据包能够按照正确的顺序进行重组,因为数据包可能会乱序到达。三次握手通过交换 SYN 和 ACK 消息来同步双方的序列号,从而为后续的可靠传输打下基础。
-
避免不必要的连接请求和不可靠的连接:
- 如果只通过一次握手,可能会导致连接不可靠,或者出现因丢包等原因导致无法确认连接是否已建立的情况。两次握手也不够,可能会发生连接建立不完整,导致数据丢失或无法正确通信。三次握手通过三次互相确认和响应,确保连接的可靠性。
-
防止老连接的残余数据影响新连接:
- 如果没有三次握手,客户端和服务器在建立连接时可能会收到来自旧连接的数据包(例如,网络中的延迟或缓存中的数据)。三次握手通过初始的 SYN 信号确保双方只处理新连接的数据,从而避免旧连接的数据包干扰新连接的建立。
三次握手的详细过程
-
第一次握手(客户端 → 服务器):
- 客户端 向 服务器 发送一个 SYN 包,请求建立连接。这个包携带客户端的 初始序列号(ISN),表示客户端准备建立连接。
- 客户端进入 SYN_SENT 状态,等待服务器的确认。
-
第二次握手(服务器 → 客户端):
- 服务器 收到客户端的 SYN 包后,表示服务器愿意建立连接,并向客户端发送一个 SYN-ACK 包。
- 这个包不仅表示服务器同意建立连接,还会携带 服务器的初始序列号,并确认客户端的 SYN 包(通过 ACK)。
- 服务器进入 SYN_RECEIVED 状态,等待客户端的最终确认。
-
第三次握手(客户端 → 服务器):
-
客户端 收到服务器的 SYN-ACK 包后,发送一个 ACK 包,确认服务器的 SYN 包。
-
此时,客户端确认服务器的序列号,并且服务器确认客户端的序列号。
-
客户端进入 ESTABLISHED 状态,准备开始数据传输。
-
在这之后,连接就正式建立,双方可以开始数据交换。
为什么三次握手而不是两次或更多次?
-
两次握手的不足:
-
四次握手的冗余:
- 如果进行了四次握手,虽然会更加精确地确认连接的状态,但实际上已经没有必要,因为三次握手足够确保双方的同步性和连接的可靠性。
- 四次握手会浪费资源和时间,因此在 TCP 中,三次握手是最合理的选择。
三次握手的作用总结:
- 确保双方都准备好接收和发送数据:通过三次握手,双方确认彼此的存在,并为后续的数据传输做好准备。
- 同步双方的序列号:通过交换 SYN 和 ACK 消息,确保双方的数据包能按顺序传输。
- 防止陈旧数据影响新连接:三次握手可以避免因旧连接的数据包干扰,确保建立的新连接能够正常通信。
- 连接的可靠性:通过三次交换,确保连接建立的可靠性,避免无效或不完全的连接。