前言
TCP的三次握手和四次挥手。
一、TCP的三次握手
三次握手目的:为了让双方都知道可以互相通信。
第一次握手:
客户端将标志位SYN
置1,随机产生序列号seq=x,并将该数据包发送给服务端,客户端进入SYN_SENT
状态,等待服务端确认。
第二次握手:
服务端收到数据报后由标志位SYN
=1知道客户端在请求建立连接,服务端将标志位SYN
和ACK
都置为1,ack=x+1,随机产生一个序列号seq=y,并将该数据包发送给客户端以确认连接请求,服务端进入SYN_RCVD
状态。
第三次握手:
客户端收到确认后检查,如果正确则将标志位ACK
置为1,ack=y+1,并将该数据包发送给服务端,服务端进行检查如果正确则连接建立成功,客户端和服务端都进入ESTABLISHED
状态,完成三次握手,开始传输数据。
【注】
为什么需要三次?
如果只是两次握手,最多只有客户端的序列号能够被确认,服务端的序列号则得不到确认
(服务端不知道 C收和S发)。
【注】半连接队列:服务器处于SYN_RCVD
状态时,会把此状态下的请求连接放在一个队列中,该队列被称为半连接队列。
【注】SYN攻击:利用TCP的协议缺陷,发送大量的半连接请求,占用半连接队列,耗费资源。
优化:缩短SYN Timeout时间;记录IP,若收到某个重复IP的报文,则将该IP的所有报文都丢弃。
二、TCP的四次挥手
第一次挥手:
客户端发送一个FIN
,用来关闭客户端到服务端的数据传输,客户端进入FIN_WAIT1
状态。
第二次挥手:
服务端收到FIN
后,发送一个ACK
给客户端,确认序号为收到序号加1,服务端进入CLOSE_WAIT
状态,客户端进入FIN_WAIT2
状态。此时的TCP、处于半关闭状态,即:客户端没有要发送的数据了,但是服务端若要发送数据,则客户端仍要接收。
第三次挥手:
服务端发送一个FIN
,用来关闭服务端到客户端的数据传输,服务端进入LAST_ACK
状态。
第四次挥手:
客户端收到FIN
后,客户端进入TIME_WAIT
状态,接着发送一个ACK
给服务端,确认后,服务端进入CLOSED
状态,完成四次挥手。
【注】
为什么需要四次?
当服务端收到客户端的FIN数据包后,服务端可能还有数据没发完,不会立即close。
所以服务端会先将ACK发过去告诉客户端我收到你的断开请求了,
但请再给我一点时间,用来发送剩下的数据报文,发完之后再将FIN发给客户端表示现在可以断了,
之后客户端收到FIN后发送ACK确认断开信息给服务端。
【注】TIME_WAIT
状态定时经过2MSL后关闭,为什么?
MSL即报文最大生存时间。在Linux系统中2MSL约为1分钟,设置2MSL可以保证上一次连接的报文已经在网络中消失,不会出现与新的TCP连接报文冲突的情况。并且保证第四次挥手的ACK能被接收到。
三、TCP的状态转换
SYN_SENT
状态
SYN_RCVD
状态
ESTABLISHED
状态
FIN_WAIT1
状态
CLOSE_WAIT
状态
FIN_WAIT2
状态
LAST_ACK
状态
TIME_WAIT
状态
CLOSED
状态