这是一个关于TCP三次握手与四次挥手原理的详细解释。
TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。“面向连接”意味着在数据传输前,通信双方必须先建立一条逻辑连接,传输结束后再释放。三次握手用于建立连接,四次挥手用于释放连接。
理解握手和挥手,需要先知道几个TCP报文头部的关键标志位:
SYN=1 表示这是一个连接请求或连接接受报文。ACK=1 表示确认字段是有效的。通常,除了最初建立连接的SYN包,后续所有报文ACK都应为1。FIN=1 表示发送方数据已发送完毕,要求释放连接。ack之前的数据已确认收到。目的:确认双方的发送和接收能力都正常,并同步初始序列号。
详细过程:第一次握手(客户端 -> 服务器):
SYN = 1,表示请求建立连接。seq = J。ACK = 0(因为这是初始请求,没有需要确认的)。SYN_SENT 状态。第二次握手(服务器 -> 客户端):
SYN = 1,ACK = 1。seq = K。ack = J + 1(表示“我收到了你的序列号J,期待你下次从J+1开始发”)。SYN_RCVD 状态。第三次握手(客户端 -> 服务器):
ACK = 1(此时SYN=0,因为连接已建立)。seq = J + 1(因为第一次握手的SYN包消耗了一个序列号)。ack = K + 1(表示“我收到了你的序列号K”)。ESTABLISHED 状态。ESTABLISHED 状态。至此,连接建立成功,可以开始数据传输。主要是为了防止已失效的连接请求报文突然又传送到服务器,导致服务器资源浪费(防止“旧的重复SYN”造成连接错乱)。
目的:双方都确认数据发送完毕,并安全地、无遗漏地关闭连接。由于TCP是全双工的(可以同时双向传输),每个方向必须单独关闭。
详细过程:假设客户端主动发起关闭。
第一次挥手(客户端 -> 服务器):
FIN = 1,ACK = 1(通常也携带对之前数据的确认)。seq = u(等于已传送数据最后一个字节序号+1)。FIN_WAIT_1 状态。第二次挥手(服务器 -> 客户端):
ACK = 1。ack = u + 1(确认客户端的FIN请求)。seq = v。CLOSE_WAIT 状态。客户端收到这个ACK后,进入 FIN_WAIT_2 状态。第三次挥手(服务器 -> 客户端):
FIN = 1,ACK = 1。seq = w(如果中间又发了数据,w会大于v)。ack = u + 1(保持不变)。LAST_ACK 状态。第四次挥手(客户端 -> 服务器):
ACK = 1。seq = u + 1(因为第一次挥手消耗了一个序号)。ack = w + 1。TIME_WAIT 状态,等待 2MSL(两倍的最大报文段生存时间)后,才彻底关闭进入 CLOSED 状态。CLOSED 状态。因为TCP是全双工,关闭需要两个独立的“提议-确认”过程。
CLOSE_WAIT 状态,是因为服务器可能还有数据需要处理并发送,不能立即回复FIN。| 特性 | 三次握手(建立连接) | 四次挥手(释放连接) |
|---|---|---|
| 目的 | 同步序列号,确认双方收发能力 | 双方安全、完整地关闭连接 |
| 发起方 | 客户端 | 可以是客户端或服务器(图示以客户端为例) |
| 关键状态 | SYN_SENT, SYN_RCVD, ESTABLISHED |
FIN_WAIT_1/2, CLOSE_WAIT, LAST_ACK, TIME_WAIT |
| 次数必要性 | 防止失效连接请求造成错误 | TCP全双工,两个方向需独立关闭 |
| 后续特殊状态 | 无 | 客户端有 TIME_WAIT(2MSL) |
这个机制是TCP实现可靠数据传输的基石之一。