一、握手策略
为了可以准确的将数据准确无误地送达目标主机,所有基于 TCP 实现的协议,都需要先完成 TCP 协议的三次握手策略。
1. 首先我们需要了解一下图中提到的几个标志符:
1.序号seq
seq 是TCP通信过程中,某一个传输方向上字节流的第一个字节的序号,当发起方发送数据时,会对此进行标记。通过这个序号seq,来确认发送数据的有序性。比如:客户端的序列号为1000,发送了1000,下一次发送的序列号就是2000,以此类推。
2.确认序号ack
ack 是TCP对上一次通信中序号seq做出的确认号,将接收到的序号seq加1 ack = seq + 1。但是只有ACK标志位为1时,确认序列号才有效。
3.标志位
标志位包括:URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:
SYN:同步标志位,用于建立会话连接、同步序号seq。
ACK:确认标志位,对已收到的数据包进行确认。确认序号是否有效,ACK为1时表示有效,
为0时表示无效。
FIN: 完成标志位,表示已经没有数据要发送了,关闭一个连接。
PSH:推送标志位,接收方应该尽快将这个报文交给应用层。
RST:重置连接。
URG:紧急指南有效。
注意⚠️
序号ack 和 标志位ACK 是不同的两个概念,不要混淆。
2. 三次握手描述
所谓三次握手,是指建立一个TCP连接时,需要客户端和服务端相互总共发送3个报文。
第一次握手:
客户端将TCP报文标志位SYN置为1,表示请求建立连接,并随机产生一个序号值seq=x,保存在TCP首部的序列号字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端的确认。
第二次握手:
服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN 和ACK都置为1,ack=x+1,并随机产生一个序号值seq=y,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
第三次握手:
客户端收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给服务器端,服务器端检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
为什么需要三次握手呢?
因为client客户端发出的连接,可能会在某个网络节点长时间滞留,当延误到某个连接释放后的某个时间才到达server服务端时,这已经是一个失效的报文段了,但服务器也会处理相应连接请求。如果不是三次握手,那么这个时候,这个失效的报文就会导致连接成功,但一直不会发送任何
数据,而服务端确一直等待接收数据,这会导致服务端不必要的资源浪费,因此,需要三次握手。
二、挥手策略
四次挥手即终止一个TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个数据包,以确认连接的断开。
第一次挥手:
客户端发起挥手请求,向Server端发送标志位为FIN的报文段,设置序列号seq,此时Client端进入FIN_WAIT_1状态,这表示Client端没有数据要发送给Server端了。

第二次挥手:
Server端收到了Client端发送的FIN报文段,向Client端返回一个标志位是ACK的报文段,ack设为
seq加1,Server端进入FIN_WAIT_2状态,Server端告诉Client端,我确认并同意你的关闭请求。
第三次挥手:
Server端向Client端发送标志位是FIN的报文段,请求关闭连接,同时Client端进入LAST_ACK状态。
第四次挥手:
Client端收到Server端发送的FIN报文段,向Server端发送标志位是ACK的报文段,然后Client端
进入TIME_WAIT状态。Server端收到Client端的ACK报文段以后,就关闭连接。此时,Client端等待2MSL的时间后依然没有收到回复,则证明Server端已正常关闭,Client端也可以关闭连接了。
为什么需要四次挥手呢?
因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了,服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了,但我服务端还有一些数据没发完,等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端,就是这里多出来了一次)。
Client为什么需要等待2MSL才关闭呢?
MSL表示报文最大生存时间,超过这个时间,报文将被丢弃。2MSL表示两倍的时间。