正所谓,工欲善其事,必先利其器。 我们要想搞懂三次握手必须得先知道一些基础的东西。
我们先分析一下上图的英文都是啥东西。 SYN: 代表连接请求/连接接受 ACK: 确认 ack: 确认号 seq:序号 客户机下面有三个框里面分别是: CLOSED SYN-SENT ESTAB-LISHED 这代表主机的三个状态。 服务器下面有四个框分别是: CLOSED LISTEN SYN-RCVD ESTAB-LISHED 这代表服务器的四个状态。 CLOSED: 表示初始状态 CLOSED大家应该都知道是关闭的意思。 其实这里的CLOSED是关闭上次握手的东西。所以说CLOSED也就是初始化的意思。 LISTEN: 监听状态。表示服务器端的某个SOCKET处于监听状态。 所以说客户机是没有监听状态的,因为客户机是主动的一方。 SYN-SENT(客户机): 客户端调用连接,发送一个SYN请求建立一个连接,在发送连接请求后等待匹配的连接请求,此时状态为SYN_SENT。 简言之: 就是我(客户机)给你(服务器)发个消息说咱俩连接吧! 等待你确认和我连接的状态。 SYN-RCVD(服务器): 在收到客户机发来的连接请求和自己发送一个可以连接,等待对方对连接请求的确认的状态。 简言之: 我(服务器)同意和你(客户机)连接,我(服务器)等你(客户机)确认和我(服务器)说话的过程。 ESTAB-LISHED: 连接已经建立,两台机器正在传输数据的状态。基础的东西都知道了,那么我们再来分析三次握手的过程。
第一次握手: 客户机发送SYN=1, seq=x(随机的序号) 这时客户机进入SYN-SENT状态。 简言之: 我(客户机)发送一个连接请求,并说我这个报文的序号是x。 第二次握手: 服务器在收到客户机发来的SYN(连接请求)后,进入了SYN-RCVD状态。 服务器并发送:SYN=1(接受连接),ACK=1(确认),ack=x+1(客户机下次需要发送的报文序号) 和seq=y(服务器发送报文序号) 简言之: 我(服务器)答应连你,确认收到你的消息了。 下次你(客户机)给我发上次发送的报文(x)的后一个(即x+1.因为这个我有了 我要下一个)。我发送报文序号是y。 第三次握手: 客户机发送ACK=1,seq=x+1,ack=y+1 这时候客户机和服务器就开始进入传输数据(ESTAB-LISHED)的状态。 简言之: 我知道你接受我的连接请求了,这次我发送的报文序号是(x+1),你下次给我发送y+1这个序号的报文。 最后将我们理解的术语和专业术语的TCP三次握手的过程来个对比。看到上图的对比,是不是发现 TCP三次握手的过程彻底明白了。
那为啥要三次握手呢? 第一次握手: 服务器知道了: 客户端的发送是正常的 自己的接收也是正常的。 第二次握手: 客户端知道了 : 服务器的发送是正常的,接收也是正常的。 自己的发送是正常的,接收也是正常的。 第三次握手: 服务端知道了: 自己的发送是正常的,客户端的接收也是正常的。 三次握手后: 客户端知道了: 自己的发送接收都正常,也知道了服务器的接受和发送是正常的。 服务器知道了: 自己的发送接收都正常,也知道了客户端的接受和发送是正常的。 所以需要三次握手。同样的在了解四次挥手前我们也得弄懂一些东西。 我们先分析一下上图的英文都是啥东西。
客户机下面有五个框里面分别是: ESTAB-LISHED FIN-WAIT-1 FIN-WAIT-2 TIME-WAIT CLOSED 这代表主机的五个状态。 服务器下面有四个框分别是: ESTAB-LISHED CLOSE-WAIT LAST-ACK CLOSED 这代表服务器的四个状态。 ESTAB-LISHED 在三握里已经知道了是 连接建立。 CLOSED 是关闭连接。 FIN-WAIT-1(客户机): FIN_WAIT_1状态是当客户机在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文, 此时该客户机即 进入到FIN_WAIT_1状态.这时双方的连接都还没有断。 FIN-WAIT-2(客户机): 当对方(服务器)回应ACK报文后(即对方确认可以断开后),则进入到FIN_WAIT_2状态。 这时候是半连接状态。即客户机要求关闭连接,客户机不发送数据了 但服务器暂时还有点数据需要传送给客户机,稍后再关闭连接。 TIME_WAIT(客户机): 表示收到了服务器的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。 如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时, 可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。 简言之: 收到了对方(服务器)的断开标志(FIN)并确认(ACK)后,这时说明服务器确认断开连接且没有数据要传了, 客户机可以直接从FIN-WAIT-1到TIME-WAIT状态。 CLOSE-WAIT(服务器): 等待客户机发来的连接中断请求 ,服务器收到FIN后, 就发出ACK以回应FIN请求,服务器进入CLOSE_WAIT状态。 LAST_ACK(服务器): 服务器在发送FIN报文后,最后等待客户机的ACK报文。这个状态就是LAST_ACK。 当收到ACK报文后,服务器进入到CLOSED可用状态了。基础的东西都知道了,那么我们再来分析四次挥手的过程。
第一次挥手: 客户机发送FIN=1,seq=u 之后进入了FIN-WAIT-1状态。 简言之: 客户机发送了一个断开连接的标志(FIN=1)。 并说这个报文的序号是u。接着客户机就进入了等待服务器确认的状态(FIN_WAIT-1)。 第二次挥手: 服务器发送ACK=1,seq=v,ack=u+1 后服务器进入了CLOSE-WAIT状态。客户机进入FIN-WAIT-2状态。 简言之: 服务器说我确认收到你的断开请求了(ACK=1),我发送的报文序号是v, 下次你(客户机)给我(服务器)发送u+1这个序号的报文。 服务器开始处理剩余的一些数据(CLOSE-WAIT)。客户机等服务器处理完剩余的数据给自己发送确认信号(FIN-WAIT-2) 第三次挥手: 服务器发送 FIN=1,ACK=1,seq=w,ack=u+1 随后服务器进入LAST-ACK状态。 简言之: 服务器给客户机发送了一个断开连接的标志(FIN=1),确认收到你的断开请求了(ACK=1), 我的发送的报文序号是w,你(客户机)下次给我(服务器)发送u+1这个序号的报文。 因为在此之前客户机并没有再次的给服务器发送报文。所以服务器给客户机要的报文序号还是u+1。 服务器等待客户机给自己发送确认收到的报文(LAST-ACK)。 第四次挥手: 客户机发送ACK=1,seq=u+1,ack=w+1,服务器随后进入TIME-WAIT状态。 服务器收到后进入CLOSED状态。等2MSL时间后客户机也进入CLOSED状态。 简言之: 客户机给服务器说我知道你可以断开了(ACK=1),我(客户机)发送的报文的序号是u+1, 你(服务器)下次给我(客户机)发送的报文序号是w+1。服务器收到客户机的确认后没啥可说的,就关闭连接了。 客户机等了2MSL后服务器没有动静了就也关闭连接了。 最后将我们理解的术语和专业术语的TCP四次挥手的过程来个对比。看到上图的对比,是不是发现 TCP四次挥手的过程彻底明白了。
最后我们来分析一下为啥客户机要等待2MSL的时间才关闭连接? MSL: 最长报文段的寿命。那2MSL就是报文段一来一回的最长时间。 如果客户机等待的时间小于2MSL。 当客户机给服务器发送确认报文,服务器没有收到时。这时候服务器就会再次的进行三次挥手的过程。 但是当第三次挥手的报文到达客户机时,客户机这时候已经关闭连接了。那么此时服务器就无法进入关闭状态。 那客户机等待时间大于2MSL呢? 大于2MSL的话就浪费时间了。 因为2MSL已经是报文段一来一回的最长时间了,如果服务器没有收到客户机的确认。 在2MSL时间内客户机是一定会再次收到的。所以2MSL是最好的等待时间。最后,三次握手我借鉴了这个视频: https://www.bilibili.com/video/BV1vA411i7rs 里面讲的很不错。