TCP三次握手四次挥手

3,467 阅读7分钟

每次面试的时候都会多多少少聊一点TCP/IP协议,那么你是如何理解其中的三次握手四次挥手的?

什么是“三次握手,4次挥手“?

首先我们需要知道TCP是一种面向连接的单播协议。

单播协议一般指单播路由协议,单播路由协议是通过路由器将到网际网络上某一位置的通信从源主机转发到目标主机。网际网络至少有两个通过路由器连接的网络。路由器是网络层中介系统,用于根据公用网络层协议(如 TCP/IP)将多个网络连接在一起。网络是通过路由器连接,并与称为网络地址或网络 ID 的同一网络层地址相关联的联网基础结构(包括中继器、集线器和桥/ 2 层交换机)的一部分。

TCP可以看成是一种字节流,他会处理IP层或以下层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的的参数,这些参数可以放在TCP头部

所以TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用4次挥手来关闭一个连接。

图示为

三次握手的过程

三次握手你可以想象成这样的一个场景,有两个两个人A和B,A想给B一些包裹,B想收一些包裹,但是A害怕给B刚发了包裹,B就走了,包裹到了以后没有收,而B则害怕A只是口头上说要把包裹寄过来,B在这里等了半天发现自己被耍了。所以这两个人需要达成一个规定或者说是一个协议来保证双方都能达到目的。这就需要三次握手。

三次握手:A对B说我要给你发一些包裹!B问A说你真的要给我发包裹吗!然后A回答我真的真的要给你发包裹(B就像言情剧的女主一样,A说的第一遍B是不信的,非要A再说一遍B才信)至此A和B的协议达成,A就可以给B发包裹啦.

这是一种比喻,真正的表现为:

(1)第一次握手:

客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认。

(2)第二次握手:

服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态。

(3)第三次握手:

客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

注意:以上动作发送的包中没有任何数据,等三次握手完成后客户端与服务器才正式开始传送数据。并且理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP连接都将被一直保持下去。

那么为什么要三次握手?

为什么要三次握手,我握两次不行吗?我觉得我说发,你说好,不就完了吗,非要矫情一下,握第三次手的意义是什么?

首先我们先来理解一下为什么需要握手?

客户端和服务器端通信前需要连接,而”握手“作用就是为了证明,**客户端的发送能力和服务器端的接受能力都是正常的,**这是”握手“来达到的目的。

第一次握手:客户端发送网络包,服务器端收到了,这样服务器端就能证明:客户端的发送能力、以及服务器端的接收能力都是正常的。

第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。 从客户端的视角来看,我接到了服务端发送过来的响应数据包,说明服务端接收到了我在第一次握手时发送的网络包,并且成功发送了响应数据包,这就说明,服务端的接收、发送能力正常。而另一方面,我收到了服务端的响应数据包,说明我第一次发送的网络包成功到达服务端,这样,我自己的发送和接收能力也是正常的。

第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力,服务端的发送、接收能力是正常的。 第一、二次握手后,服务端并不知道客户端的接收能力以及自己的发送能力是否正常。而在第三次握手时,服务端收到了客户端对第二次握手作的回应。从服务端的角度,我在第二次握手时的响应数据发送出去了,客户端接收到了。所以,我的发送能力是正常的。而客户端的接收能力也是正常的。

而从上面的过程可以看到,最少是需要三次握手过程的。两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论。

四次挥手

TCP连接时双向传输的对等的模式,就是说双方都考验同时向对方发送或者接收数据。当有一方要关闭连接时,会发送指令告知对方,我要关闭连接了。这时对方会回一个ACK,此时一个方向的连接关闭。但是另一个方向仍然可以继续传输数据,等到发送完了所有数据后,会发送一个FIN段来关闭此方向上的连接。接收方发送ACK确认关闭连接。

通俗的来说就是

四次挥手: A对B说:我要和你断开连接!B说:好的,断吧! B也对A说我也要和你断开连接!

A说:好的,断吧!

真实的过程是

(1)第一次挥手

客户端主动关闭方发送一个FIN,用来关闭客户端到服务器端的数据传送,也就是客户端告诉服务器端:我已经不会再给你发数据了, (当然,在 fin 包之前发送出去的数据,如果没有收到对应的 ack 确认报文,客户端依然会重发这些数据),但是,此时客户端还可以接受数据

(2)第二次挥手

服务端收到FIN包后,发送一个ACK给客户端,确认序号为收到序号+1(与 SYN 相同,一个 FIN 占用一个序号)。

(3)第三次挥手

服务器端发送一个FIN,用来关闭服务器端到客户端的数据传送,也就是告诉客户端,我的数据也发送完了,不会再给你发送数据了!!!

(4)第四次挥手

客户端收到 FIN 后,发送一个 ACK 给服务端,确认序号为收到序号 + 1,至此,完成四次挥手。

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

这是因为服务端在LISTEN(监听)状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方ACK和FIN一般都会分开发送。