• 一个小故事讲清楚TCP三次握手和四次挥手


    TCP三次握手有很多文章来讲述,不过我总觉得有点抽象,这次打算通过一个“打印机”的小故事来讲解三次握手和四次挥手.

    一.三次握手

    TCP提供面向连接的服务,在传送数据前必须建立连接,TCP连接是通过三次握手建立的。

    1.1 标准说明

    三次握手过程
    三次握手过程:

    • 一开始两方都处在closed状态,当服务端监听到客户端的请求,服务端的状态 会进入到listen状态
    • 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(seq=x),此时客户端处于 SYN_SENT 状态
    • 第二次握手:服务端收到客户端的SYN报文后,用自己的SYN报文进行应答,并指明自己服务端的初始化序列号(seq=y),此外为了确认客户端的SYN,会将客户端的ISN(也就是x)+1作为ack的值(ack=x+1).此时服务端处于SYN_RCVD状态
    • 第三次握手:客户端收到SYN报文之后,会发送一个ACK报文,报文里面会将服务端的ISN(就是y)+1作为ack值(ack=y+1).此时客户端处于ESTABLISHED 状态.服务端收到ACK报文之后,服务端也进入ESTABLISHED 状态,此时连接建立,可以开始通信

    1.2 “打印机小故事”

    TCP三次握手通俗过程
    有一次工作,小赵希望用打印机打点材料,可是自己电脑没驱动,就想着喊小王帮忙打一下.

    • 第一次握手: 小赵先喊:“我是小赵,小王你在不?”
    • 第二次握手:小王听到是小赵,然后回复:“小赵,我是小王,我在,啥事啊?”
    • 第三次握手: 小赵一听,小王回消息了,证明可以找他帮忙了,然后赶忙说: “小王,我需要打印材料,一会发你材料,你等我片刻”
    • 然后小王就知道小赵要打印东西了,就开始准备打印机,等小赵发材料了

    1.3 TCP 握手为什么是三次,为什么不能是两次?

    1.是防止服务端开启无用的连接增加服务器的开销
    2.防止已失效的连接请求报文段突然又到了服务端,引发错误.

    1.3.1 防止服务端建立无用的连接增加服务器开销

    由于网络传输是存在网络阻塞的可能行,如果在服务端发送了SYN报文之后,没有第三次握手,服务端不知道这个报文是否客户端能接收到.这种情况下,服务端就会认为当前端口可用,端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。这样一来,就会有很多无效的连接端口白白地开着,导致资源的浪费
    在这里插入图片描述

    简单来说,就是小王听到小赵喊话之后,回复“小赵,我是小王,我在”.然后小赵就不回任何消息了.小王不知道小赵听没听到回复的消息,也不知道小赵之后要干什么,所以只能一直等待,这样就造成小王其他的事情也干不了.

    1.3.2 防止已失效的连接请求报文段突然又到了服务端,引发错误

    还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。
    在这里插入图片描述
    所以我们需要“第三次握手”来确认这个过程:

    通过第三次握手的数据告诉服务端,客户端有没有收到服务器“第二次握手”时传过去的数据,以及这个连接的序号是不是有效的。若发送的这个数据是“收到且没有问题”的信息,接收后服务器就正常建立 TCP 连接,否则建立 TCP 连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。

    1.4 TCP 握手为什么不能是四次?

    简单说,就是三次挥手已经足够创建可靠的连接,没有必要再多一次握手导致花费更多的时间建立连接

    1.5 三次握手中每一次没收到报文会发生什么情况

    • 第一次握手服务端未收到SYN报文

    服务端不会进行任何的动作,而客户端由于一段时间内没有收到服务端发来的确认报文,等待一段时间后会重新发送SYN报文,如果仍然没有回应,会重复这个过程,直到发送次数超过最大重传次数限制,就会返回连接建立失败。

    • 第二次握手客户端未收到服务端响应的ACK报文

    客户端会继续重传,直到次数限制;而服务端此时会阻塞在accept()处,等待客户端发送ACK报文

    • 第三次握手服务端未收到客户端发送过来的ACK报文

    服务端同样会采用类似客户端的超时重传机制,如果重试次数超过限制,则accept()调用返回-1,服务端建立连接失败;

    而此时客户端认为自己已经建立连接成功,因此开始向服务端发送数据,但是服务端的accept()系统调用已经返回,此时不在监听状态,因此服务端接收到客户端发送来的数据时会发送RST报文给客户端,消除客户端单方面建立连接的状态。

    二. 四次挥手

    2.1 标准说明

    四次挥手过程:

    在这里插入图片描述

    四次挥手过程:

    • 数据传输结束之后,通信双方都可以主动发起断开连接请求,这里假定客户端发起
    • 第一次挥手:客户端发送一个断开连接的FIN报文,报文中指定一个序列号(seq=u),此时客户端处于FIN_WAIT_1的状态
    • 第二次挥手:服务端收到FIN报文后,发送一个ACK报文,报文中指定一个自己服务端的序列号(seq=v)和将收到的客户端序列号的值+1作为ack值(ack=u+1),表明已经收到客户端的报文了,此时服务端处于CLOSED_WAIT状态
    • 第三次挥手:服务端发送释放连接的FIN报文,和第一次挥手中客户端一样,指定一个自己的序列号(seq=w),此时服务端处于LAST_ACK状态
    • 第四次挥手:客户端收到服务端的FIN报文后,和第二次挥手一样发送一个ACK报文(ACK=1 seq=u+1 ack=w+1),此时客户端处于TIME_WAIT状态.等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

    2.2 “打印机小故事”后续

    上回说到小赵让小王帮忙打印材料,可是材料总有打完的时候.此时小赵发现需要打印的材料都已经发送给小王了,就准备告诉小王差不多可以结束了

    • 首先小赵告诉小王,材料都发你了,就这些了,不用再打了,差不多可以技术了
    • 小王收到消息后,回复说我知道了,目前打印机里面还有几个正在打的,这些打完就收工
    • 等材料都打好之后,小王告诉小赵,都打印完了,你看看少没少,需要重打不?
    • 小赵检查了一下,东西不缺,告诉小王,东西都全,一个不少,可以收拾一下回去了.然后小赵等待一会,看小王没有消息了,自己也就收拾东西走了.至于小王,收到小赵通知可以结束的消息之后,也就收拾走了.

    在这里插入图片描述

    2.3 为什么需要四次挥手

    通过“打印机小故事”明显看出来,服务端在收到客户端断开连接FIN报文后,并不会立即关闭连接,而是先发送一个ACK包先告诉客户端收到关闭连接的请求,只有当服务器的所有报文发送完毕之后,才发送FIN报文断开连接,因此需要四次挥手.

    2.4 为什么需要等待 2MSL

    1. 为了保证客户端发送的最后一个 ACK 报文段能够到达服务端。网络存在丢包问题,怕最后一次客户端发送的ACK报文丢失,导致服务端因没有收到报文一直处在LAST_ACK状态中,无法关闭.如果在一段时间服务端没有收到报文,会重发FIN报文,此时客户端收到报文之后,会重新发送ACK报文,并将等待时间重置为2MSL.直到最后客户端和服务端都进入CLOSED状态

    2. 防止已失效的连接请求报文段出现在本连接中.经过2MSL时间,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失.这样就可以使下一个连接中不会出现这种旧的连接请求报文段。

    2.5 为什么等待的时间是2MSL?

    MSL( Maximum Segment Lifetime),最大报文生存时间.它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃。

    至于为什么是2倍,是考虑存在双方发送的情况.客户端端先发送一个报文,在一个MSL后到达服务端,然后服务端作出响应,经过一个MLS到达客户端.一去一回正好2MSL
    在这里插入图片描述

    三.整体过程

    一个完整的三次握手四次挥手如下图所示:
    在这里插入图片描述

    参考文献

    1. https://mp.weixin.qq.com/s/yAlErlC09GnjaVvwUo3Acg
    2. https://vue3js.cn/interview/http/handshakes_waves.html#%E4%B8%80%E3%80%81%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B
    3. https://juejin.cn/post/6908327746473033741#heading-82
  • 相关阅读:
    重要的SQL 查询语法
    集合导题、刷题、考试全套完整流程,专业强大的功能,提高刷题学习效率和企业的培训效率
    node.js+vscode安装与配置
    解决 Vue3 + Element Plus 树形表格全选多选以及子节点勾选的问题
    Linux 进程概念
    .NET6 supersocket 全双工发送和接收消息
    uniapp+vue基于Android的图书馆借阅系统qb4y3-nodejs-php-pyton
    7、Docker网络
    idea导入eclipse项目的时候,Java图标变成黄色小J了,怎么解决?
    TCP/IP(十)TCP的连接管理(七)CLOSE_WAIT和TCP保活机制
  • 原文地址:https://blog.csdn.net/baidu_33438652/article/details/125458696