TCP三次握手,四次握手标准回答

210 阅读4分钟

三次握手:

交换序列号,确定最大报文段长度

过程:

 第一次握手:起初两端都处于CLOSED关闭状态,Client将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server,Client进入SYN-SENT状态,等待Server确认; 

第二次握手:Server收到数据包后由标志位SYN=1得知Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN-RCVD状态

 第三次握手:Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client和Server就可以开始传输数据。

为什么要三次握手,两次不可以么?

为了防止 已失效的链接请求突然又传送到了服务端, 因而产生错误。

客户端发出的链接请求报文并未丢失,而是在某个网络节点长时间滞留了,以致延误到链接释放以后的某个时间才到达Server。这时,Server 误以为这时Client发出的一个新的链接请求,于是就向客户端发送确认数据包,同意建立链接。若不采用三次握手,那么只要Server发出确认数据包,新的链接就建立了。由于Client此时并未发出建立链接的请求,所以不会理睬Server的确认,也不与Server通信;而这时Server一直在等待Client的请求,就白白浪费了一定的资源。若采用三次握手,由于Server端没有收到来自客户端的确认,就会知道Client并没有要求建立请求,就不回建立链接。

四次握手:

(主机1: 我要和你断开链接;主机2: 好的,断吧;

   主机2: 我要和你断开链接;主机1: 好的,断吧)

第一次握手:主机1发送一个链接释放报文(包括FIN标志位为1,序列号),用来关闭主机1到主机2的数据传送,主机1进入FIN_WAIT_1状态。

第二次握手:主机2收到FIN后,发送一个确认报文(包括ACK标志位为1,确认序号为收到信号+1,和序列号)给主机1,确认序号为收到信号+1,主机2 进入CLOSE_WAIT状态。主机1收到确认报文后进入FIN_WAIT_2状态。此时TCP链接处于半关闭状态,主机1已经不能发送数据给主机2,不过主机2仍然可以向主机1发送数据。

第三次握手:主机2发送一个链接释放报文(包括FIN=1,序列号;ACK=1,确认号),用来关闭主机2到主机1的数据传送,主机2进入LAST_ACK状态。

第四次握手:主机1收到FIN后,发送确认报文(包括ACK=1,确认序号为收到序号+1,和序列号)给主机2,随后主机1进入TIME_WAIT状态,经过2MSL(最长报文段寿命的2倍时长)后才释放TCP连接。 主机2收到确认报文后就会立马释放TCP链接,进入CLOSED状态。

为什么客户端发出第四次挥手的确认报文后要等2MSL的时间才能释放TCP连接?

考虑丢包的问题。

如果第四次握手的报文丢失,服务端没收到确认报文就会重发第三次握手的报文,这样报文一去一回的最长时间就是2MSL,客户端可以在这段时间里收到服务端重新发送的FIN报文并重发ACK,继续四次握手。如果客户端等待2MSL后依然没有等到来自服务端的报文,就可以确认服务端已经收到第四次握手的报文并关闭链接,这时客户端也可以放心关闭了。