图解TCP三次握手和四次挥手

TCP的几个状态

SYN------------>建立连接

FIN------------->关闭连接

ACK------------->响应

PSH------------->有数据传输

RST------------->连接重置

TCP三次握手

C:我要和你建立连接!

S:你真的要和我建立连接吗?

C:我真的要和你建立连接,成功!
在这里插入图片描述

第一次握手:

客户端向服务器发送一个SYN连接请求报文段。并将标志位SYN置为1,随机产生一个序号字段(seq=J表示为客户端数据的初始序号),并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。

第二次握手:

服务器端接收到数据包后,为该连接分配一个TCP缓存和变量,然后向客户端发送SYN ACK请求,标志位都置为1,同时服务器端随机产生一个序号字段(seq=K表示为服务器端数据的初始序号),确认序号为客户端发送的序号加1(ack=J+1表示数据流从此位置开始)。将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。

第三次握手:

客户端收到确认后,也会为此次TCP连接分配缓存和变量,检查ack=J+1以及ACK是否为1,如果正确则将ACK标志位置为1.确认号字段为ack=K+1,并将该数据包发送给服务器端,要它给出确认,服务器端检查确认ack=K+1是否正确、ACK是否为1,如果正确则连接建立成功。客户端和服务器端都进入ESTABLISHED状态,完成三次握手,随后两者之间可以开始传输数据了。

TCP四次挥手

C:今天就到这了,晚安!

S:等一会儿,我还有事要说。

S:我说完了,晚安,好梦!

C:我舍不得你,你先睡。

C:等了2MSL之后睡了。

在这里插入图片描述

第一次挥手:
客户端向服务器端发送一个FIN,用来申请关闭客户端与服务器端的连接,并将其标志位置为1,随机产生一个序号字段seq=M,客户端进入FIN_WAIT_1状态。

第二次挥手:

服务器端接收到FIN后,向客户端发送一个ACK(表示已经接接收到了客户端关闭连接的请求,以后将不再接收客户端发送过来的数据),将其标志位置为1,此时ack=M+1,并且服务器端也随机产生一个序号seq=N,进入CLOSE_WAIT状态。

客户端收到服务器端的确认请求后,进入FIN_WAIT_2状态。此时TCP连接处于半关闭状态,即客户端已经没有要发送的数据了,但服务器端若想要发送数据,客户端依然要接收。

第三次挥手:

服务器端将最后的数据发送完毕之后,向客户端发送FIN,申请断开与客户端的连接,并将FIN、ACK标志位置为1,ack=M+1。由于在半关闭状态,服务器端很可能又发送了一些数据,所以也会产生序号字段seq=K,进入LAST_ACK状态,等待客户端的确认。

第四次挥手:

客户端接收到FIN后,必须发出确认ACK,并将其标志位置为1,ack=K+1,客户端此时的序号字段为seq=M+1,此时客户端进TIME_WAIT状态。

(注意:此时TCP连接还没有释放,必须经过2MSL的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态)

服务器端只要接收到了客户端的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。


为什么三次握手中客户端最后还要发送一次确认呢?

第三次握手协议主要是防止已经失效的连接请求又传到服务器端造成错误。

如果是两次握手建立连接,服务端在没有确定客户端是否对自己做出正确应答的情况下就建立连接, 当客户端因意外使所发的请求报文没有及时到达,服务端收到该请求以为客户端需 要建立连接,直接进入ESTABLISHED状态,服务端会一直等待客户端发送数据, 造成资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。


TIME_WAIT 的意义(为什么要等于 2MSL)

第一,保证客户端发送的最后一个ACK报文能够到达服务器。若客户端发完确认应答后直接进入 CLOSED 状态,那么如果该ACK报文丢失,服务端等待超时后就会重新发送连接释放请求,但此时客户端已经关闭了,不会作出任何响应,因此服务端永远无法正常关闭

(站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。)

第二,防止出现已经失效的连接请求报文段出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。


为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。

而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

猜你喜欢

转载自blog.csdn.net/PILIpilipala/article/details/114311483