26.TCP连接的三次握手,断开连接的四次挥手

发布于:2023-01-23 ⋅ 阅读:(489) ⋅ 点赞:(0)

前提了解:

 如上图所示,TCP头部主要包括以下信息:
1、源端口号 (16位):数据包的发送方端口

2、目标端口号 (16位):数据包的接收方端口

3、序列号 seq(32位):在请求连接的时候操作系统会分配一个32位的数作为序列号,用来标识一个数据包在发送中的位置。

TCP为应用层数据中的每个字节都分配了一个seq号,TCP就是利用seq来实现的可靠传输。

TCP中的seq指的是TCP数据包中应用层数据的第一个字节对应的序列号。

4、确认应答号 ack(32位):表示发送端中seq在ack之前的所有字节都已经被接收方接收了,接收方下一个希望接收的seq是ack。

5、 4个主要标识位

(1)SYN
SYN = 1,代表这个数据包是客户端和服务器之间连接数据包。

(2)ACK
ACK = 1,代表这个数据包是一个答复包,用于确认收到的数据包。

(3)FIN
FIN = 1,说明这是一个单方面结束连接的数据包

(4)RST
RST = 1,说明TCP连接出现异常强制断开连接。
 

1.TCP三次连接(三次握手):

(1)图解:

状态:Closed:没有任何连接状态       

          Listen:侦听来自远方TCP端口的连接请求

         SYN-SENT:同步发送状态——在发送连接请求后等待匹配的连接请求        

         SYN-RECEIVED:同步收到状态——在收到和发送一个连接请求后等待对方连接请求的确认

         ESTABLISHED:代表一个打开的连接,数据可以传送给用户

信号:SYN:同步位。SYN=1表示进行一个连接请求

           ACK:确认位。ACK=1表示确认有效

           ack:确认号

           seq:序号

 (2)过程:

握手之前:主动打开连接的客户端Closed阶段,被动打开的服务器端也结束Closed阶段,并进入Listen阶段。

第一次握手:

首先客户端向服务端发送一段连接请求报文,其中:建立连接请求控制段(SYN=1);seq=x表示传输的报文段的第一个数据字节的序列号为x,此序列号代表整个报文段的序号;客户端进入SYN-SENT(同步发送状态)

第二次握手:

服务器发回确认报文段,同意建立新连接的确认段(SYN=1);确认序号字段有效(ACK=1);服务器告诉客户端报文序号是y(seq=y);ack=x+1表示服务器已经收到客户端序号为x的报文段,准备接收客户端序列号为x+1的报文段;服务器由LISTEN进入SYN-RCVD(同步收到状态)。

第三次握手:

客户对服务器的同一连接进行确认,确认序号字段有效(ACK=1);客户此次的报文段的序号是seq=x+1;客户期望接收服务器序列号为ack=y+1的报文段;

当客户端发送ack时,客户端进入ESTABLISHED状态;当服务收到客户端发送的ack后,也进入到ESTABLISHED状态;第三次握手可携带数据。

 (3)为什么需要三次握手?

第一次握手:客户发送请求,此时服务器知道客户能发;

第二次握手:服务器发送确认,此时客户知道服务器能发能收;

第三次握手:客户发送确认,此时服务器知道客户能收;

(4)为什么是三次握手而不是两次握手?

假设采用两次握手建立连接,客户端向服务端发送了一个SYN包,来请求建立连接,因为某些未知的原因,并没有到达服务器,在中间某个网络节点产生了滞留,为了建立连接客户端会重发SYN包,这次数据包正常送达,服务端回复SYN+ACK之后建立起了连接,但是第一包数据阻塞的网络节点突然恢复,第一包SYN包又送达到服务端。这时服务端会误认为是客户端又发起了一个新的连接,从而两次握手之后进入等待状态,服务端认为是两个连接,而客户端认为是一个连接,造成了状态不一致。两次握手的机制将会让客户端和服务端再次建立连接,这将导致不必要的错误和资源的浪费。

2.TCP连接的拆除(四次挥手):

(1)图解:

 状态:ESTABLISHED:

           FIN-WAIT-1:等待远程TCP的连接中断请求,或先前的连接中断请求的确认;

           CLOSE-WAIT:等待从本地用户发来的连接中断请求;

           FIN-WAIT-2:从远程TCP等待连接中断请求;

           LAST-ACK:等待原来发向远程TCP的连接中断请求的确认;

           TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认;

信号:FIN=1:表示这是一个断开连接的数据包

第一次挥手:

客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号seq=u(u等于前面已经传过来的数据的最后一个字节的序号+1),此时客户端进入FIN-WAIT-1(终止等待1)状态。注意:TCP规定,FIN报文段即使不携带数据,也要消耗一个序列号。

第二次挥手:

服务器收到连接释放报文后,发出确认报文,ACK=1,ack=u+1 ,并且带上自己的序列号seq=v,此时服务端就进入到了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据发送了,但是服务端向客户端发送数据,客户端依旧要接收。这个状态要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

(客户端收到服务器的确认后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这儿之前还需要接收服务器发送的最后的数据))

第三次挥手:

服务端最后的数据发送完之后,就向客户端发送连接释放报文:FIN=1,ACK=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号seq=w,此时服务端就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手: 

客户端收到服务端的连接释放报文后,必须发出确认:ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时客户端就进入TIME-WAIT(时间等待)状态。注意此时TCP还没有释放,还需要等待2MSL(最长报文段寿命)的时间后,客户端撤销相应的TCB后,就结束了这次TCP连接。

(服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB之后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些)