【计算机网络】TCP 三次握手与四次挥手详解

一、三次握手

           所谓三次握手即建立 TCP 连接,就是指建立一个TCP 连接时,需要客户端和服务端总共发送 3 个包确认连接的建立。在 socket 编程中,这一过程由客户端执行 connect 来触发。整个流程如下

                                           

                                                                                      TCP 三次握手图


1、第一次握手:Client 将标志位 SYN 置为 1,随机产生一个值 seq= x,并将该数据包发送给 Server, 然后 Client 进入 SYN_SENT 状态,等待 Server 确认。

 2、第二次握手:Server 收到数据包,由 SYN = 1 知道 Client 请求建立连接, Server 将标志位  ACK ,SYN 都置为 1,ack = x+1,随机产生一个值 seq = y,并将该数据包发送个给 Client 以确认连接请求 , Server 进入 SYN_RECVD 状态。

 3、第三次握手:Client 收到确认后,检查 ack 是否是为 y+1 ,如果正确则将标志位 ACK 置为 1,ack = y+1,并将该数据包发送给 Server ,Server 检查确认 ack 是否为 y+1 ,ACK 是否为 1,如果正确,则连接建立成功。Client 和 Server 进入 ESTABLISHED 状态,完成三次握手。接下来就可以进行数据传输了。


二、TCP 四次挥手

所谓四次挥手即终止 TCP 连接,就是指断开一个 TCP 连接时,需要客户端和服务端总共发送 4 个包以确认连接 的断开。在 socket 编程中,这一过程由客户端或服务端任何一方执行,这个流程如下:

                                                 

                                                                                                TCP 四次挥手过程

        由于 TCP 连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个 FIN 来终止这一方向上的连接,收到一个 FIN 只是意味着这一方向上没有数据流动了,即不会再接收数据了,但是在这个 TCP 连接上仍然能够发送数据,直到这一方向上也发送了 FIN 。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。  

1、第一次挥手:Client 发送一个 FIN,FIN 的值是置为1 的,并产生一个自己的序号 seq = u。用来关闭 Client 到 Server 的数据传送,Client 进入到 FIN_WAIT1 状态。

         2、第二次挥手:Server 收到 FIN 后,将 ACK 置为1,产生一个确认号 ack = u+1。er然后 发送 ACK 给 Client,Server 进入 CLOSE_WAIT 状态。

         3、第三次挥手:Server 在发送一个 FIN,用来关闭 Server 到 client 的数据传输,Server 进入到 LAST_ACK 状态。

4、第四次握手: Client 接收到 FIN 后,CLient 进入到 TIME_WAIT 状态,接着发送一个 ACK 到 Server ,ACK =1 ,确认号为收到的序号 加 1,Server 进入到 CLOSED 状态,完成四次挥手。

  三、常见面试题:

1、为什里么 TCP 建立连接时是三次握手,而关闭连接时是四次握手?

答:这是应为服务器端的 LISTEN 状态下的 socket 当收到 SYN 报文的连接请求后,它可以把 ACK 和 SYN(ACK 起应答作用,SYN 起同步作用)放在同一个报文段里来发送。但关闭连接时,当收到 对方的 FIN 报文通知时,它仅仅表示对方没有数据发送给你了。但未必你所有的数据都发送给对方了,所以你可能未必会马上关闭 socket ,也即你可能还需要发送一些数据给对方之后,在发送 FIN 报文给对方来表示你同意现在可以关闭连接了,所以这里的 ACK 和 FIN 报文多数情况下都是分开发的。

  2、为什么不能用两次握手进行连接?

答:3 握手中完成两个重要的功能,即双方既要做好发送数据 的准备工作(双方都知道彼此已经准备好),也允许双方就初始序列号进行协商,这个序列号在握手的过程中被发送和确认。

把三次握手改成两次握手,可能会发生死锁。例如,计算机 S 和 C 之间通信,假定 C 给 S 发送了一个连接请求分组,S 收到了这个分组,并发送了确认答应分组。按照两次握手的协定,S 认为连接已经成功得建立了,可以开始发送数据分组。可是, C 在 S 的答应分组在传输中被丢失的情况下,将不知道 S 是否已经准备好,不知道 S 建立什么样的序号, C 甚至怀疑 S 是否已经收到自己的请求连接分组。在这种情况下,C 认为连接还未建立成功,将忽略 S 发来的任何分组,只等待连接确认答应分组。而 S 在发出的分组超时后,重复发送同样的分组。这就形成了死锁。

3、为什么  A 在 TIME_WAIT 状态必须等待 2MSL 的时间呢 ?这有连个理由。

答:(1)、为了 保证 A 发送的最后一个 ACK 能够到达 B 。这个 ACK 报文段有可能丢失,因而使处在 LAST_ACK 状态的 B 收不到对已发送的  FIN + ACK 报文段的确认。B 会超时重传这个 FIN + ACK 报,报文段,而 A 就能在 2 MSL 时间内收到这个重传的 FIN+ACK 报文段。接着 A 重传一次确认,重新启动 2MSL计时器。最后 A 和 B 能正常进入CLOSED状态。如果 A 在 TIME_WAIT 状态不等待一段时间,而是在发送完 ACK 报文端后立即释放掉连接,那么久无法收到 B 的 FIN + ACK 报文段,因此,也不会在发送一次确认报文段。这样 B 就无法按正常步骤进入到 CLOSED 状态。

(2)、防止已失效的连接请求报文段出现在本连接中。 A 发送完最后一个 ACK 报文段后 ,再经过 2 MSL,就可以使本地连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接不会出现在这种旧的请求连接报文中。

4、TCP 和 UDP 的 区别什么?

答:

(1)、TCP 是有连接的,而UDP是无连接的。有连接指的是开始传输实际数据之前 TCP 的客户端和服务器必须通过三次握手建立连接,会话之后也要结束 连接。

        (2)、TCP 保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是 UDP 不能保证按序到达,甚至不保证达到。只是努力交付,即便是按序发送的序列,也不保证按序到达。

(3)、TCP 首部需要 20 个字节(不算可选项)。UDP 首部只需要 8 个字节。

        (4)、TCP 有流量控制和拥塞控制,UDP 没有,网络拥塞不会影响发送端的发送速率。

(5)、TCP 是一对一的连接、而UDP可以支持 一对一、一对多、多对多的通信。

(6)、TCP 是面向字节流的服务。UDP 是面向报文的服务。