TCP连接的建立和关闭过程及相关面试问题详解(三次握手&四次挥手&面试问题)

三次握手、四次挥手问题是面试中一定会问到的,包括在《高质量C/C++编程》一书中也有类似的习题。这篇blog就TCP连接的建立和关闭过程及相关面试问题做一个详解,如有错误,望指正。

如果对TCP还不了解,可以先阅读这篇文章:
TCP固定头部结构详解

三次握手:

三次握手是就是TCP在建立连接时的过程。 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接。

这里写图片描述

A主机运行TCP客户端程序,B主机运行TCP服务器端程序,在A主机发送SYN之前,客户端和主机都处于CLOSED状态。

B主机先创建传输控制块PCB。准备接收客户端的请求,然后服务器端进入LISTEN状态,等待客户端连接请求。

  • 第一次握手

TCP客户端先创建传输控制块PCB,然后向服务器B发送连接请求报文段,此时首部中的同步位SYN置位1,同时选择一个初始序号seq = x,这是TCP客户端进入SYN-SENT(同步已发送)状态。

  • 第二次握手

服务器B收到A发送的连接请求报文段后,如果同意连接,则向A发送确认,
在确认报文段中,将ACK和SYN都置为1,确认号是ack = x + 1,同时也为自己选择一个初始序号seq = y,这是TCP服务器进入SYN-RCVD(同步收到)状态。

  • 第三次握手

TCP客户端收到B发送的确认后,还要向B给出确认,确认报文ACK置为1,确认号ack = y + 1,自己的序号为seq = x + 1。TCP协议规定,ACK报文段可以携带数据,如果不携带数据,则不消耗序号,则下一数据报文段的序号仍然为seq = x + 1,这时TCP已经建立连接,A进入ESTABLISHED(已建立连接状态)。当B收到A的确认后也进入ESTANLISHED状态。

上面这种建立连接的过程称为三次握手。

【面试问题1】为什么A还要再发送一次确认呢?

这是为了防止某些失效的连接请求报文再次传送给服务器B而导致出错。
失效连接报文来源?
假如TCP连接就是两次握手,如果说客户端A给服务器端B发送了连接请求报文段,但是报文段丢失,导致B没有收到,于是A重传连接请求,第二次的服务器端B收到了连接请求,建立了连接。数据传输完成后就释放连接。在这个过程中,客户端A共发送两次连接请求报文,一个报文丢失,另一个报文到达了B。不存在“已失效的连接报文”。

现在考虑另一种特诉情况,主机A第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机B,主机B以为是主机A又发起的新连接,于是主机B同意连接,并向主机A发回确认,但是此时主机A根本不会理会,主机B就一直在等待主机A发送数据,导致主机B的资源浪费。

四次挥手:

四次挥手是TCP释放连接的过程,具体过程请看下图分析。

TCP断开连接的过程

完成数据传输后,通信的双方都可以释放连接,主机A、B先都处于ESTABLISHED状态。

  • 第一次挥手

A的应用进程先向其TCP发送连接释放报文段,A停止再发送数据,主动关闭TCP连接,A把连接释放报文段首部的FIN置1,其序号seq = u,它等于前面已经传送过的数据的最后一个字节序号加1。这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认,注意:TCP规定,FIN报文段即使不携带数据也要消耗一个序号。

  • 第二次挥手

B收到连接释放报文段后,立即发出确认,确认号是ask = u + 1,而这个报文段自己的序号是v,等于B前面已传送过的数据的最后一个字节的序号加1。然后B就进入CLOSE-WAIT(关闭等待)状态,TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP处于半关闭状态,即A已经没有数据要发送了,但B若要发送数据,A仍要接收,也就是说,从B到A的方向连接并灭有关闭。这个状态可能会持续一些时间。

  • 第三次挥手

A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接请求释放报文段。

若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN = 1,现假定B的序号为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号akc = u + 1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

  • 第四次挥手

A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack = w + 1,而自己的序号是seq = u + 1(根据TCP标准,前面发送的FIN报文段要消耗一个序号)。然后进入到TIME-WAIT(时间等待)状态。请注意,现在TCP连接连接还没有释放掉。必须经过时间等待计时器(TIME-WAIT)设置的时间2MSL后,A才进入到CLOSED状态。时间MSL叫做最长报文段寿命。MSL是根据工程来设置时长的,假设为2min。因此从A进入到TIME-WAIT状态后,要经过4分钟才能进入到CLOSED状态,才能开始建立下一个新的连接。当A撤销相应的传输控制块TCB后,就结束了这次的TCP连接。

【面试问题2】为什么A在TIME-WAIT状态必须等待2MSL的时间呢?

这有两个原因:
第一:为了保证A发送的最后一个ACK报文段能够到达B,这个报文段有可能丢失,因而使处在LAST-WAIT的状态B收不到对方已发送的FIN-ACK报文段的确认,B会超时重传这个FIN + ACK报文段,而A就能在2MSL时间内接收到这个重传的FIN + ACK报文段,接着A重传一次确认,重新启动2MSL计时器。最后,A和B都正常进入到CLOSED状态。如果A在TINE-WAIT装态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么久无法收到B重传的FIN + ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法按正常步骤进入CLOSED状态。
第二:防止上文提到的“已失效的连接请求报文”出现在本连接中。A发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样可以使下一个新的连接中不会出现这种旧的连接请求报文段。
B只要收到A发出的确认,就进入CLOSED状态,同样,B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接,我们注意到,B结束TCP连接的时间要比A早一些。

猜你喜欢

转载自blog.csdn.net/m0_37925202/article/details/80903455
今日推荐