三次握手
- 第一次握手:
客户端给服务端发一个 SYN 报文,SYN=1,初始序号seq=x
。此时客户端处于 SYN_SEND
状态
- 第二次握手:
服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,SYN=1,ACK=1,确认号ack=x+1
,初始序号seq=y
。此时服务器处于 SYN_RCVD
的状态。
- 第三次握手:
客户端收到 SYN 报文之后,会发送一个 ACK=1
的报文,确认号ack=y+1
表示已经收到了服务端的 SYN 报文。此时客户端处于 ESTABLISHED
状态,服务器收到 ACK 报文之后,也处于 ESTABLISHED
状态,此时,双方已建立起了连接。
为什么两次不行
如果首先客户端发送了 SYN 报文,但是滞留在网络中,TCP 以为丢包了,然后重传,两次握手建立了连接。等到客户端关闭连接了。但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,那么服务端接收到了,然后发送相应的数据表,就又建立了链接,但是此时客户端已经关闭连接了,所以造成了资源浪费。
四次挥手
- 第一次挥手:
客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。
即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(
终止等待1)状态,等待服务端的确认。
- 第二次挥手:
服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT
状态,客户端收到服务端的确认后,进入FIN_WAIT2
(终止等待2)状态,等待服务端发出的连接释放报文段。
- 第三次挥手:
服务端的数据传输结束,断开连接,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK
状态,等待客户端的确认。
- 第四次挥手:
客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT
状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED
状态。
MSL 是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,不过在实际应用中可以通过设置 SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口