一文轻松搞懂三握四挥!

首先我们要知道的是TCP的数据传输过程分为三个阶段:建立连接、数据传输、连接释放。而三次握手、四次挥手主要解释的是建立连接和连接释放的过程。

其次,TCP通信都是基于C/S架构,即服务端--客户端模式, 下面我们正式开始解析:

三次握手:

一文轻松搞懂三握四挥!_第1张图片

 首先,我们先对其中的英文名词进行解释:

报文:

SYN:(同步位)仅在建立连接的前两个报文段中使用。(即请求连接、接受连接)SYN报文段不能携带数据,但需要消耗一个序列号

seq:请求报文的序号                ACK:确认报文(只有0、1两个值)                       

ack:对方发来数据的确认号,即表示在此序号之前的数据都已经收到,现在期望收到序号为此值的数据

客户端和服务端的状态:

CLOSED:关闭上次握手,即这次握手的初始化状态               

SYN-SENT(客户端):客户端调用连接,发送一个SYN请求建立一个连接,在发送连接请求后等待匹配的连接请求,此时状态为SYN_SENT。

                        简言之 :就是我(客户机)给你(服务器)发个消息说咱俩连接吧! 等待你确认和我连接的状态。

SYN-RCVD(服务端):在收到客户机发来的连接请求后,自己发送一个连接请求,等待对方对连接请求的确认的状态。

                        简言之:我(服务器)同意和你(客户机)连接,我(服务器)等你(客户机)确认和我(服务器)说话的过程。

ESTAB-LISHED:连接已经建立,两台机器正在传输数据的状态。

注:对于客户机和服务器的定义并不是绝对的,我们将主动发起连接的一方叫做客户机,将能够应答的一方称为服务器, 如果TCP连接同时打开,那么双方将既是客户机又是服务器。

此时,基础知识已经介绍完毕,接下来分析三次握手的具体过程:

第一次握手:客户机发送SYN=1,请求报文序号seq=x,此时客户机进入SYN-SENT状态

        简言之:我(客户机)发送一个连接请求,我这个请求报文的序号是x,并且进入等待服务器回应的状态

第二次握手:服务器在接收到客户机发送的连接请求SYN=1后,向客户机发送接受连接SYN=1,确认报文ACK=1,服务器发送的报文序号seq=y,期望下次客户机发来的报文序号ack=x+1,之后服务器进入SYN-RCVD状态。

注:该报文段是ACK报文段的同时也是SYN报文段,所以该报文段也不能携带数据。

        简言之:我(服务器)答应连你,确认收到你的消息了。 下次你(客户机)给我发上次发送的报文(x)的后一个(即x+1,因为这个我有了 我要下一个)。我发送报文序号是y。并且进入等待客户机回应的状态

第三次握手:收到服务器发送的报文后,客户机发送确认报文ACK=1,服务器期望收到的报文序号seq=x+1,期望下次服务器发送来的报文序号ack=y+1,之后客户机首先进入数据传输状态(ESTAB-LISHED),服务器接受到报文后也进入数据传输状态(ESTAB-LISHED)

        简言之:我知道你接受我的连接请求了,这次我发送的报文序号是(x+1),你下次给我发送y+1这个序号的报文。

那为什么要三次握手呢?为什么不是两次握手呢?

  • 为了阻止历史的重复连接初始化造成的混乱问题;
  • 防止使用 TCP 协议通信的双方建立了错误的连接。

设想:如果只有两次握手,那么第二次握手后服务器只向客户端发送ACK包,此时客户端与服务器端建立连接。在这种握手规则下:

假设:如果发送网络阻塞,由于TCP/IP协议定时重传机制,B向A发送了两次SYN请求,分别是x1和x2,且因为阻塞原因,导致x1连接请求和x2连接请求的TCP窗口大小和数据报文长度不一致,如果最终x1达到A,x2丢失,此时A同B建立了x1的连接,这个时候,因为AB已经连接,B无法知道是请求x1还是请求x2同B连接,如果B默认是最近的请求x2同A建立了连接,此时B开始向A发送数据,数据报文长度为x2定义的长度,窗口大小为x2定义的大小,而A建立的连接是x1,其数据包长度大小为x1,TCP窗口大小为x1定义,这就会导致A处理数据时出错。

         很显然,如果A接收到B的请求后,A向B发送SYN请求y3(y3的窗口大小和数据报长度等信息为x1所定义),确认了连接建立的窗口大小和数据报长度为x1所定义,A再次确认回答建立x1连接,然后开始相互传送数据,那么就不会导致数据处理出错了。

四次挥手:

一文轻松搞懂三握四挥!_第2张图片

 首先,先对图中的名词进行解释:

报文:

FIN:请求断开连接的标志位                                        seq:请求报文的序号                                       

ack:对方发来数据的确认号,即表示在此序号之前的数据都已经收到,现在期望收到序号为此值的数据

客户端和服务端的状态:

ESTAB-LISHED:两台机器正在传输数据的状态。

FIN-WAIT-1(客户端):当客户机在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该客户机即 进入到FIN_WAIT_1状态(这时双方的连接都还没有断)

FIN-WAIT-2(客户端):当对方(服务器)回应报文ACK=1后(即对方确认可以断开后),则进入到FIN_WAIT_2状态。

                                注:TCP 服务器进程通知高层应用进程。从 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭状态(此时只能由被动关闭方服务器,向主动关闭方客户端发送数据),B 若发送数据,A 仍要接收

TIME-WAIT(客户端):客户端收到了服务器发来的断开连接请求FIN=1,发出ACK=1的确认报文后,进入TIME-WAIT等待2MSL(即两个最大报文段生存周期)后关闭TCP连接进入CLOSED状态

                                注:如果FIN_WAIT_1状态下,就收到了对方同时带 FIN标志和ACK标志的报文, 可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

                        简言之:收到了对方(服务器)的断开标志(FIN)并确认(ACK)后,这时说明服务器确认断开连接且没有数据要传了, 客户机可以直接从FIN-WAIT-1到TIME-WAIT状态。

CLOSE-WAIT(服务端):服务器收到客户端发来的连接中断请求FIN=1后,就发出确认报文ACK=1以回应FIN请求,此时服务器进入CLOSE_WAIT状态。即等待将剩余数据发送完毕的状态

LAST-ACK(服务端):服务器在发送完所有数据后,发送连接中断请求FIN=1,最后等待客户机的ACK报文。这个状态就是LAST_ACK。 当收到ACK报文后,服务器进入到CLOSED可用状态了。

下面我们正式开始分析四次挥手的过程: 

 第一次挥手:客户机发送连接中断请求FIN=1,发送报文的序号为seq=u,之后客户机进入FIN-WAIT-1

        简言之:客户机发送了一个断开连接的标志(FIN=1)。 并说这个报文的序号是u。接着客户机就进入了等待服务器确认的状态(FIN_WAIT-1)。

第二次挥手: 服务器发送确认报文ACK=1,确认号ack=u+1(期望下次客户机发来此序号的报文),并且此报文序号为seq=v,之后服务器进入CLOSE-WAIT

        简言之:服务器说我确认收到你的断开请求了(ACK=1),我发送的报文序号是v, 下次你(客户机)给我(服务器)发送u+1这个序号的报文。 服务器开始处理剩余的一些数据(CLOSE- WAIT)。客户机等服务器处理完剩余的数据给自己发送确认信号(FIN-WAIT-2)

                注:由于只能由被动关闭方向主动关闭方发送数据,而此次服务器没有发送关闭连接请求,所以客户端还是只能被动接收数据,不能主动发送数据

 第三次挥手:服务器处理完所有数据,发送断开连接请求FIN=1,确认报文ACK=1,确认号ack=u+1(期望下次客户机发来此序号的报文),此次报文的序号为seq=w,之后进入最后确认断开状态(LAST-ACK)

        简言之:服务器给客户机发送了一个断开连接的标志(FIN=1),确认收到你的断开请求了(ACK=1),我的发送的报文序号是w,你(客户机)下次给我(服务器)发送u+1这个序号的报 文。因为在此之前客户机并没有再次的给服务器发送报文。所以服务器给客户机要的报文序号还是u+1。服务器等待客户机给自己发送确认收到的报文(LAST-ACK)。

第四次挥手: 客户端发送确认报文ACK=1,确认号ack=w+1,此次报文序号为seq=u+1,。服务器收到此条报文后进入CLOSED状态,客户机进入TIME-WAIT状态等待2MSL后也进   入CLOSED状态。

        简言之:客户机给服务器说我知道你可以断开了(ACK=1),我(客户机)发送的报文的序号是u+1, 你(服务器)下次给我(客户机)发送的报文序号是w+1。服务器收到客户机的确认后 无需多言,就关闭连接了。 客户机等了2MSL后服务器没有动静了就也关闭连接了。

此时我们来分析

1、为什么客户端要等待2MSL的时间再关闭?

 MSL: 最长报文段的寿命。那2MSL就是报文段一来一回的最长时间。
        如果客户机等待的时间小于2MSL。当客户机给服务器发送确认报文,服务器没有收到时。这时候服务器就会再次的进行第三次挥手的过程,向客户机发送断开连接请求。但是当第三次挥手的报文到达客户机时,由于客户机等待的时间小于2MSL,客户机这时候可能已经关闭连接了。那么此时服务器就无法正常的进入关闭状态。

        如果客户机等待的时间大2MSL的话就浪费时间了。 因为2MSL已经是报文段一来一回的最长时间了,如果服务器没有收到客户机的确认。 在2MSL时间内客户机是一定会再次收到的。所以2MSL是最好的等待时间。

        可以防止已失效的报文段。客户端在发送最后一个 ACK 之后,再经过经过 2MSL,就可以使本连接持续时间内所产生的所有报文段都从网络中消失,从而保证在关闭连接后,不会有仍在网络中滞留的报文段去骚扰服务器。

2、为什么建立连接三次,断开连接四次?

        因为建立连接时,服务器的确认 ACK 和请求同步 SYN 可以放在一个报文里,而断开连接时,服务器可能还有剩余数据要传送,因此,必须先发一个客户端断开连接请求的确认 ACK,以免客户端超时重传,待服务器的数据传送完毕后,再发送一个请求断开连接的报文段。

        断开时次数比连接多一次,是因为连接过程,通信只需要处理「连接」,而断开过程,通信需要处理「数据+连接」。

你可能感兴趣的:(http,网络协议,网络)