TCP 三次握手(Three-Way Handshake)是为了确保 客户端 和 服务器 之间建立一个可靠的连接,并且保证通信的双方都准备好发送和接收数据。三次握手的过程涉及三个步骤,通过这个过程,TCP 连接能够可靠地建立,并确保数据传输的可靠性和顺序性。
三次握手的过程:
-
第一次握手:客户端 → 服务器
- 客户端发送一个 SYN(同步)包给服务器,表示客户端希望建立连接。
- SYN 包包含客户端的 初始序列号(ISN),用于后续的可靠数据传输。
- 客户端进入 SYN_SENT 状态,等待服务器的响应。
具体来说:
- 客户端发送的数据包头部中的 SYN 标志位设置为 1。
- 该包携带一个 初始序列号(ISN),例如:ISN = 1000。
-
第二次握手:服务器 → 客户端
- 服务器收到客户端的 SYN 包后,表示同意建立连接,并向客户端发送一个 SYN-ACK(同步确认)包。
- SYN-ACK 包包含 服务器的初始序列号(ISN),以及对客户端 SYN 包的确认,即 ACK(确认)客户端发送的 SYN 包。
- 服务器进入 SYN_RECEIVED 状态,等待客户端的最终确认。
具体来说:
- 服务器发送的 SYN-ACK 包中,SYN 标志位设置为 1,表示同意连接。
- 该包携带 服务器的初始序列号(假设为 2000),并确认客户端的初始序列号(即:客户端的 ISN + 1)。
示例:
- 服务器向客户端发送:SYN = 1, ACK = 1, ISN = 2000, 客户端的 ISN + 1 = 1001。
-
第三次握手:客户端 → 服务器
- 客户端收到服务器的 SYN-ACK 包后,发送一个 ACK(确认)包给服务器,表示客户端已经收到服务器的确认,且连接可以建立。
- 客户端确认了服务器的序列号,并返回一个 ACK 包,表示客户端的初始序列号(ISN)已收到,并确认连接可以开始。
- 客户端进入 ESTABLISHED 状态,服务器也进入 ESTABLISHED 状态,连接建立完成。
具体来说:
- 客户端发送 ACK 包时,ACK 标志位设置为 1,表示确认。
- 该包携带 客户端的序列号(ISN + 1)和对服务器序列号的确认(服务器的 ISN + 1)。
示例:
- 客户端向服务器发送:ACK = 1, ISN = 1001(客户端的确认包),确认服务器的序列号 2000。
三次握手的目的和作用:
- 同步双方的序列号:
- TCP 是一个 字节流协议,数据传输的每个字节都有一个序列号。在三次握手中,客户端和服务器通过交换 SYN 包和 ACK 包来同步各自的 初始序列号(ISN),保证数据的顺序性和可靠性。
- 确认双方的接收和发送能力:
- 三次握手的过程能够确保双方在数据传输前都已经准备好。客户端和服务器在连接建立之前,都能确保对方能够接收数据,并且自己也可以发送数据。
- 防止旧连接的数据包干扰:
- 在没有三次握手的情况下,客户端和服务器可能会收到来自旧连接的数据包,这些数据包可能会因为网络延迟而进入新连接的通信流中。三次握手通过初步的确认机制避免了这种情况。
- 防止半开连接:
- 如果只进行一次握手或者两次握手,可能会出现客户端请求建立连接但没有收到服务器的确认,或者服务器没有收到客户端的确认。三次握手确保了双方都能够相互确认对方的连接请求,避免了半开连接的风险。
为什么是三次握手,而不是两次或四次?
- 两次握手的问题:
- 如果只进行两次握手,客户端发起连接请求,服务器响应请求,但没有确认双方的序列号和接收能力。这会导致无法确保连接双方的状态,也无法确保数据传输的顺序性,容易产生错误。
- 四次握手的问题:
- 四次握手虽然会使连接的确认更加精确,但会浪费不必要的资源和时间。实际上,三次握手已经足够完成连接的可靠建立,额外的一次握手并不必要。