三次握手和四次挥手

2019-02-11  本文已影响0人  奋斗live

TCP/IP在连接之前,会有3次沟通,简称“三次握手”,在断开连接之前,会有四次沟通,简称“四次挥手”。
了解这个连接沟通之前,先来了解下,两个序号和3个标志位:

这里有个注意的点,确认序号ack和标志位中的ACK是不同的,别搞混了。
确认方ack=发起方req+1

(1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
(3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
(A)URG:紧急指针(urgent pointer)有效。
(B)ACK:确认序号有效。
(C)PSH:接收方应该尽快将这个报文交给应用层。
(D)RST:重置连接。
(E)SYN:发起一个新连接。
(F)FIN:释放一个连接。

三次握手建立TCP连接

image.png

这里假设主动打开的是A,被动打开的是B

在发送的第一条消息中,A随机选取一个序列号作为初始序号(x)发送给B
第二次消息B使用ack对A的第一次数据包进行确认,因为已经接收到A的序列号为x的数据包了,接下去则准备接收序列号为x+1的包,所以ack=x+1,并且告诉A自己的初始序号,seq = y
第三条消息 A是对B发送的消息进行确认,并且建立连接。前面说了,B开始准备接收A的序列号为x+1的数据包,所以seq=x+1,而ack=y+1则是A准备接收B序列号为y+1的数据包。

有个问题,建立连接,A已经发送给B一次消息了,为什么还需要发送一次呢?

这主要为了防止已失效的连接请求报文段突然又传送到B。
“已失效的连接请求报文段”是这样产生的。假设A发送一个连接请求,但是因连接请求丢失,B未收到确认。于是A再重传一次连接请求,并且B正常收到,再给A回传确认,A再回传确认,正常建立连接。等数据传输完毕,释放连接。A发送的两个请求,其中一个丢失,其中一个正常到达了B。没有“失效的连接请求报文段”。

假设目前出现了一个异常情况。A发送的第一个连接请求报文段并没有丢失,而是因为网络太慢了,在网络节点滞留了,导致在 A释放连接(A第二个连接请求完成,并释放连接)后到达了B。这样这第一个连接请求报文段就成了失效的报文段。B收到这个失效的报文段,就会误以为是A又发出一个新的连接请求。于是向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就 建立了。

由于现在A并没有发出建立连接的请求,不会理睬B的确认,也不会向B发送数据。但B却傻傻地以为连接已经建立了,并一直等待A发来数据。于是B的资源就被浪费了。

三次握手就可以避免上面异常情况的发生。采用三次握手,B就知道连接并没有建立,不会傻傻地进行等待,浪费资源。

四次挥手断开连接

由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭。


image.png

1、客户端发出断开连接请求报文,并且停止发送数据,进入FIN_WAIT_1
2、服务器收到连接释放报文,进入CLOSE_WAIT(此时,虽然客户端停止了向服务器发送数据,但是服务器向客户端还是可以继续发送数据的,客户端还是需要接受)
3、客户端收到服务器的确认请求后,进入FIN_WAIT_2,等待服务器发送断开连接报文
4、等到服务器把数据全部发送完之后,就向客户端发送断开连接报文,服务器进去LAST_ACK
5、客户端收到服务器的连接释放报文后,进入TIME_WAIT
6、服务器只要收到客户端发出的确认,立即进入CLOSED状态,结束连接。

现在有个问题,为什么客户端发送完TIME_WAIT之后还有等待2MSL?

1、为了保证最后的确认报文能够到达服务器,因为在网络上,这个ACK报文可能会丢失。站在服务器的角度,我已经发送了FIN+ACK 释放连接报文,客户端还没有给我反应,应该是我发送的报文它没有收到,于是我就重新发送一次释放连接报文。而客户端就能在这个2MSL时间段内收到这个重传报文,接着给出回应,并且重启2MSL计时器。
2、就是防止上面提到的已失效的连接请求报文段出现在本连接中,A在发送完最有一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失

上一篇下一篇

猜你喜欢

热点阅读