TCP三次握手四次挥手
一、基础理论
1、TCP的标志位
标志位 | 含义 |
---|---|
SYN(synchronous) | 在建立连接时使用,表示请求同步序列号。当SYN=1时,该数据段用于发起一个连接。 |
ACK(acknowledgement) | 用于确认接收到的数据段,如果ACK=1,确认应答的字段变为有效 |
FIN(finish) | 在关闭连接时使用,当FIN=1时,表示发送端已完成数据发送任务,希望断开连接。 |
RST(reset) | 用于复位异常或无效的连接,或者拒绝非法的数据段,当RST=1时,表示 TCP 连接中出现异常必须强制断开连接。 |
PSH(push) | 指示接收端应该尽快将数据交付给上层应用程序,而不是等到缓冲区满后再交付。 |
URG (Urgent Pointer) | 当URG=1时,报文中有紧急数据需要立即处理,此时包含紧急指针字段来指示紧急数据的末尾位置。 |
2、TCP的状态码
状态码 | 含义 |
---|---|
CLOSED | 没有任何连接状态 |
LISTEN | 服务器端处于监听状态,等待客户端发起连接请求。 |
SYN_SENT | 在发送连接请求后等待确认 |
SYN_RCVD | 服务器收到客户端的SYN,并发回一个SYN+ACK作为响应,等待客户端确认。 |
ESTABLISHED | 连接建立,可以进行正常的数据传输 |
FIN_WAIT_1 | 已经发送关闭请求,等待确认(主动关闭) |
CLOSE_WAIT | 对方发送FIN后,本地端收到并确认后进入此状态,表示本端应用程序尚未关闭连接。 |
FIN_WAIT_2 | 收到了对方对FIN的确认后进入的状态,继续等待对方也关闭连接。 |
LAST_ACK | 已经发送了FIN,正在等待最后一个ACK以彻底关闭连接。 |
TIME_WAIT | 发送了FIN并收到ACK之后,等待足够时间确保远程主机收到最后的ACK,避免旧分组在网络中滞留导致的问题。 |
CLOSING | 同时收到了FIN且正要发送FIN时,两边都在关闭连接,但还没有收到对方对FIN的确认。 |
CLOSED(再次) | 收到并确认了对方的FIN后,最终关闭连接,回到初始状态。 |
二、TCP连接的建立与释放
1、三次握手
-
第一次握手:
- 一开始,客户端和服务端都处于
CLOSED
状态。先是服务端主动监听某个端口,处于LISTEN
状态 - 客户端发送连接请求报文段,将
SYN
标志位设置为 1,表示请求建立连接。seq
为x
。然后,客户端进入SYN_SENT
状态,等待服务器的确认; - 标志位为SYN,表示""请求建立新连接";
序号为seq=x(x一般为1);
- 一开始,客户端和服务端都处于
-
第二次握手:
- 服务器收到客户端发送的
SYN
报文段,需要对这个SYN
报文段进行确认,设置ack
为x+1(seq+1)
;同时,自己自己还要发送SYN
请求信息,将SYN
标志位置为 1,seq
为y
;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入SYN_RCVD
状态; - 标志位为SYN和ACK,表示"确认客户端的报文
seq
序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接"(即告诉客户端,服务器收到了你的数据);
序号为seq=y;
确认号为ack=x+1,表示收到客户端的序号seq并将其值加1作为自己确认号ack的值;
- 服务器收到客户端发送的
-
第三次握手:
- 客户端收到服务器的
SYN+ACK
报文段。然后将ACK
标志位设置为 1,表示确认收到服务器同意连接的信号,向服务器发送ACK
报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED
状态,完成 TCP 三次握手。 - 标志位为ACK,表示"确认收到服务器端同意连接的信号"(即告诉服务器,我知道你收到我发的数据了);
序号为seq=x+1,表示收到服务器端的确认号ack,并将其值作为自己的序号值;
确认号为ack=y+1,表示收到服务器端序号seq,并将其值加1作为自己的确认号ack的值;
- 客户端收到服务器的
2、四次挥手
-
第一次挥手:
-
客户端想要释放连接,向服务器发送
FIN
报文,将FIN
标记位设置为1,同时指定一个序列号seq=u
。随后客户端进入FIN_WAIT_1
状态。 -
标志位为FIN,表示"请求释放连接";
序号为seq=u;
-
-
第二次挥手:
-
服务器端接收到从客户端发出的
FIN
报文后,确认了客户端想要释放连接,随后服务器端会发送
ACK
报文,并且把客户端的序列号+1作为ACK
报文的序列号值。表明已经收到客户端的报文,此时服务器端处于CLOSE_WAIT
状态。 -
随后服务器端开始准备释放服务器端到客户端方向上的连接。客户端收到从服务器端发出的
ACK
应答报文,确认了服务器收到了客户端发出的释放连接请求。随后客户端结束FIN_WAIT_1
状态进入FIN_WAIT_2
状态。 -
标志位为ACK,表示"接收到客户端发送的释放连接请求";
序号为seq=v;
确认号为ack=u+1;表示是在接收到客户端报文的基础上,将其序号seq值加1作为本段报文确认号ack的值
-
-
第三次挥手:
-
服务器端自从发出
ACK
确认报文之后,经过CLOSE_WAIT
阶段,服务器端将最后数据发送完毕后就向客户端发出连接释放报文段,报文包含FIN
和ACK
标志位。随后服务器端结束CLOSE_WAIT
状态,进入LAST_ACK
状态。并且停止再服务器端到客户端方向上发送数据,但是服务器端仍然能够接收从客户端传输过来的数据。 -
标记位为FIN和ACK,表示"已经准备好释放连接了"。
序号为seq=w;
确认号为ack=u+1;
-
-
第四次挥手:
-
客户端收到来自服务器端发出的
FIN
+ACK
报文,确认了服务器端已做好释放连接的准备,结束FIN_WAIT_2
状态,并向服务器端发送一个ACK
报文作为应答,将服务器端的序列号值+1作为自己的ACK
报文的序列号值。进入TIME_WAIT
状态。 -
服务器端收到从客户端发出的TCP报文之后结束
LAST-ACK
阶段,进入CLOSED
阶段。由此正式确认关闭服务器端到客户端方向上的连接。 -
客户端等待计时器设置的时间2MSL之后,结束
TIME-WAIT
阶段,进入CLOSED
阶段,至此完成"四次挥手"。 -
标记位为ACK,表示"接收到服务器准备好释放连接的信号"。
序号为seq=u+1;表示是在收到了服务器端报文的基础上,将其确认号ack值作为本段报文序号的值。
确认号为ack=w+1;表示是在收到了服务器端报文的基础上,将其序号seq值作为本段报文确认号的值。
-
三、更多面试题参考
4.1 TCP 三次握手与四次挥手面试题 | 小林coding (xiaolincoding.com)