linux三次握手、四次挥手

news2024/11/25 5:03:17

TCP协议是一个安全的、面向连接的、流式传输协议,所谓的面向连接就是三次握手,对于程序猿来说只需要在客户端调用connect()函数,三次握手就自动进行了。先通过下图看一下TCP协议的格式,然后再介绍三次握手的具体流程。

1.tcp协议介绍

 

在Tcp协议中,比较重要的字段有:

  • 源端口:表示发送端端口号,字段长 16 位,2个字节
  • 目的端口:表示接收端端口号,字段长 16 位,2个字节
  • 序号(sequence number):字段长 32 位,占4个字节,序号的范围为 [0,4284967296]。
    • 由于TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号
    • 首部中的序号字段则是指本报文段所发送的数据的第一个字节的序号,这是随机生成的。
    • 序号是循环使用的,当序号增加到最大值时,下一个序号就又回到了0
  • 确认序号(acknowledgement number):占32位(4字节),表示收到的下一个报文段的第一个数据字节的序号,如果确认序号为N,序号为S,则表明到序号N-S为止的所有数据字节都已经被正确地接收到了。
  • 8个标志位(Flag):
    • CWR:CWR 标志与后面的 ECE 标志都用于 IP 首部的 ECN 字段,ECE 标志为 1 时,则通知对方已将拥塞窗口缩小;
    • ECE:若其值为 1 则会通知对方,从对方到这边的网络有阻塞。在收到数据包的 IP 首部中 ECN 为 1 时将 TCP 首部中的 ECE 设为 1.;
    • URG:该位设为 1,表示包中有需要紧急处理的数据,对于需要紧急处理的数据,与后面的紧急指针有关;
    • ACK:该位设为 1,确认应答的字段有效,TCP规定除了最初建立连接时的 SYN 包之外该位必须设为 1;
    • PSH:该位设为 1,表示需要将收到的数据立刻传给上层应用协议,若设为 0,则先将数据进行缓存;
    • RST:该位设为 1,表示 TCP 连接出现异常必须强制断开连接;
    • SYN:用于建立连接,该位设为 1,表示希望建立连接,并在其序列号的字段进行序列号初值设定;
    • FIN:该位设为 1,表示今后不再有数据发送,希望断开连接。
  • 窗口大小:该字段长 16 位,表示从确认序号所指位置开始能够接收的数据大小,TCP 不允许发送超过该窗口大小的数据。

2.三次握手 

Tcp连接是双向连接,客户端和服务器需要分别向对方发送连接请求,并且建立连接,三次握手成功之后,二者之间的双向连接也就成功建立了。如果要保证三次握手顺利完成,必须要满足以下条件:

  • 服务器端:已经启动,并且启动了监听(被动接受连接的一端)
  • 客户端:基于服务器端监听的IP和端口,向服务器端发起连接请求(主动发起连接的一端)

三次握手具体过程如下:

第一次握手:

  •  客户端:客户端向服务器端发起连接请求将报文中的SYN字段置为1,生成随机序号x,seq=x
  • 服务器端:接收客户端发送的请求数据,解析tcp协议,校验SYN标志位是否为1,并得到序号 x

第二次握手:

  • 服务器端:给客户端回复数据

        1.回复ACK, 将tcp协议ACK对应的标志位设置为1,表示同意了客户端建立连接的请求

        2.回复了 ack=x+1, 这是确认序号

  •        x: 客户端生成的随机序号
    • 1: 客户端给服务器发送的数据的量, SYN标志位存储到某一个字节中, 因此按照一个字节计算,表示客户端给服务器发送的1个字节服务器收到了。

        3.将tcp协议中的SYN对应的标志位设置为 1, 服务器向客户端发起了连接请求

        4.服务器端生成了一个随机序号 y, 发送给了客户端

  • 客户端:接收回复的数据,并解析tcp协议
  1. 校验ACK标志位,为1表示服务器接收了客户端的连接请求
  2. 数据校验,确认发送给服务器的数据服务器收到了没有,计算公式如下:发送的数据的量 = 使用服务器回复的确认序号 - 客户端生成的随机序号 ===> 1=x+1-x
  3. 校验SYN标志位,为1表示服务器请求和客户端建立连接
  4. 得到服务器生成的随机序号: y

第三次握手:

  • 客户端:发送数据给服务器

        1.将tcp协议中ACK标志位设置为1,表示同意了服务器的连接请求
        2.给服务器回复了一个确认序号 ack = y+1

  • y:服务器端生成的随机序号
  • 1:服务器给客户端发送的数据量,服务器给客户端发送了ACK和SYN, 都存储在这一个字节中

        3.发送给服务器的序号就是上一次从服务器端收的确认序号因此 seq = x+1

  • 服务器端:接收数据, 并解析tcp协议
  1. 查看ACK对应的标志位是否为1, 如果是1代表, 客户端同意了服务器的连接请求
  2. 数据校验,确认发送给客户端的数据客户端收到了没有,计算公式如下:给客户端发送的数据量 = 确认序号 - 服务器生成的随机序号 ===> 1=y+1-y
  3. 得到客户端发送的序号:x+1

3.tcp四次挥手

四次挥手是断开连接的过程,需要双向断开,关于由哪一端先断开连接是没有要求的。通信的两端如果想要断开连接就需要调用close()函数,当两端都调用了该函数,四次挥手也就完成了。

  • 客户端和服务器断开连接 -> 单向断开
  • 服务器和客户端断开连接 -> 单向断开

进行了两次单向断开,双向断开就完成了,每进行一次单向断开,就会完成两次挥手的动作。

  1. 第一次挥手:
  2. 主动断开连接的一方:发送断开连接的请求
  3. 将tcp协议中FIN标志位设置为1,表示请求断开连接
  4. 发送序号x给对端,seq=x,基于这个序号用于客户端数据校验的计算
  • 被动断开连接的一方:接收请求数据, 并解析TCP协议
  1. 校验FIN标志位是否为1
  2. 收到了序号 x,基于这个数据计算回复的确认序号 ack 的值

第二次挥手:

  • 被动断开连接的一方:回复数据
  1. 同意了对方断开连接的请求,将ACK标志位设置为1
  2. 回复 ack=x+1,表示成功接受了客户端发送的一个字节数据
  3. 向客户端发送序号 seq=y,基于这个序号用于服务器端数据校验的计算
  • 主动断开连接的一方:接收回复数据, 并解析TCP协议
  1. 校验ACK标志位,如果为1表示断开连接的请求对方已经同意了
  2. 校验 ack确认发送的数据服务器是否收到了,发送的数据 = ack - x = x + 1 -x = 1

第三次挥手:

  • 被动断开连接的一方:将tcp协议中FIN标志位设置为1,表示请求断开连接
  • 主动断开连接的一方:接收请求数据, 并解析TCP协议,校验FIN标志位是否为1

第四次挥手:

  • 主动断开连接的一方:回复数据
    • 将tcp协议中ACK对应的标志位设置为1,表示同意了断开连接的请求
    • ack=y+1,表示服务器发送给客户端的一个字节客户端接收到了
    • 序号 seq=h,此时的h应该等于 x+1,也就是第三次挥手时服务器回复的确认序号ack的值
  • 被动断开连接的一方:收到回复的ACK, 此时双向连接双向断开, 通信的两端没有任何关系了

4.流量控制

流量控制可以让发送端根据接收端的实际接受能力控制发送的数据量。它的具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不会超过该大小的数据,该限制大小即为窗口大小,即窗口大小由接收端主机决定。

TCP 首部中,专门有一个字段来通知窗口大小,接收主机将自己可以接收的缓冲区大小放在该字段中通知发送端。当接收端的缓冲区面临数据溢出时,窗口大小的值也是随之改变,设置为一个更小的值通知发送端,从而控制数据的发送量,这样达到流量的控制。这个控制流程的窗口也可以称作滑动窗口。

这个图是一个单向的数据发送:

左侧是数据发送端:对应的是发送端的写缓冲区(内存),通过一个环形队列进行数据管理

  • 白色格子: 空闲的内存, 可以写数据
  • 粉色的格子: 被写入到内存, 但是还没有被发送出去的数据
  • 灰色的格子: 代表已经被发送出去的数据

右侧是数据接收端:对应的是接收端的读缓冲区,存储发送端发送过来的数据

  • 白色格子:空闲的内存, 可以继续接收数据, 滑动窗口的值记录的就是白色的格子的大小
    • 随着接收的数据越来越多, 白色格子越来越少, 滑动窗口的值越来越小
    • 如果白色格子没有了, 滑动窗口变为0, 这时候, 发送端就被阻塞了
  • 粉色格子:接收的数据,但是这个数据还没有从内核中读走,使用read() / recv()
    • 粉色格子变少了, 可用空间就变多了, 滑动窗口的值就变大了
    • 如果滑动窗口的值从0变为大于0, 接收端又重新有容量接收数据了, 发送端的阻塞自动解除,继续发送数据

基于TCP通信的流程图,记录了从三次握手 -> 数据通信 -> 四次挥手是全过程:

# fast sender: 客户端
# slow recerver: 服务器
# win: 滑动窗口大小
# mss: maximum segment size, 单条数据的最大长度

第1步:第一次握手,发送连接请求SYN到服务器端

  • 0(0):0表示客户端生成的随机序号,(0)表示客户端没有额外给服务器发送数据, 因此数据的量为0
  • win4096: 客户端告诉服务器, 能接收的数据(缓存)的最大量为4k
  • mss1460: 客户端可以处理的单条最大字节数是1460字节

第2步:第二次握手

  • ACK: 服务器同意了客户端的连接请求
    • SYN: 服务器请求和客户端建立连接
  • 8000(0):8000是服务器端生成的随机序号,(0)表示服务器没有额外给客户端发送数据, 因此数据的量为0
  • 1: 发送给客户端的确认序号
    • 确认序号 = 客户端生成的随机序号 + 客户端给服务器发送的数据量(字节数) ===> 1=0+1
    • 表示客户端给服务器发送的1个字节服务器收到了
  • win6144: 服务器告诉客户端我能最多缓存 6k数据
  • mss1024: 服务器能处理的单条数据最大长度是 1k

第3步: 第三次握手

  • ACK: 客户端同意了服务器的连接请求
  • 8001: 发送给服务器的确认序号
    • 确认序号 = 服务器生成的随机序号 + 服务器给客户端发送的数据量 ===> 8001 = 8000 + 1
    • 客户端告诉服务器, 你给我发送的1个字节的数据我收到了
  • win4096: 告诉服务器客户端能缓存的最大数据量是4k

第4~9步: 客户端给服务器发送数据

  • 1(1024):1 (1-0)表示之前一共给服务器发送了1个字节,(1024)表示这次要发送的数据量为 1k
  • 1025(1024):1025(1025-0)表示之前一共给服务器发送了1025个字节,(1024)表示这次要发送的数据量为 1k
  • 2049(1024):2049(2049-0)表示之前一共给服务器发送了2049个字节,(1024)表示这次要发送的数据量为 1k
  • 第9步完成之后,服务器的滑动窗口变为0,接收数据的缓存被写满了,发送端阻塞

第10步:

  • ack6145: 服务器给客户端回复数据,6145是确认序号, 代表实际接收的字节数服务器实际接收的字节数 = 确认序号 - 客户端生成的随机序号 ===> 6145 = 6145 - 0
  • win2048:服务器告诉客户端我的缓存还有2k,也就是还有4k还在缓存中没有被读走

第11步:win4096表示滑动窗口变为4k,代表还可以接收4k数据,还有2k在缓存中

第12步:客户端又给服务器发送了1k数据

第13步: 第一次挥手,FIN表示客户端主动和服务器断开连接,并且发送了1k数据到服务器端

第14步: 第二次挥手,回复ACK, 同意断开连接

第15, 16步: 服务器端从读缓冲区中读数据, 第16步数据读完, 滑动窗口变成最大的6k

第17步:

  • FIN: 服务器请求和客户端断开连接
  • 8001(0): 服务器一共给客户端发送的字节数 8001 - 8000 = 1个字节,携带的数据量为0(FIN不计算在内)
  • ack8194: 服务器收到了客户端的多少个字节: 8194 - 0 = 8194个字节

第18步: 第四次挥手

  • ACK: 客户端同意了服务器断开连接的请求
  • 8002: 确认序号, 可以计算出服务器给客户端发送了多少数据,8002 - 8000 = 2 个字节

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1217488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python正则匹配示例

需要再如下图的txt中把 1100开头的订单号 提取出来,这个时候需要用到正则表达式 import rewith open(source.txt, r) as file:lines file.readlines()target \1100 target_lines [] for line in lines:if line.find(target) ! -1: print("match string…

java的Exception.getMessage为null

之前捕获异常后调用异常的getMessage写日志,日志写的竟然是null,不可思议。发现要调用异常的getCause().getMessage()才能得到异常信息 刻意把密码改错,让异常直达界面,免得有问题时候只能猜

LeetCode算法题解|LeetCode738. 单调递增的数字、LeetCode968. 监控二叉树

一、LeetCode738. 单调递增的数字 题目链接&#xff1a;738. 单调递增的数字 题目描述&#xff1a; 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c…

Backblaze 2023 Q3硬盘故障质量报告解读

作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告&#xff0c;给大家提供了一份真实应用场景下的稳定性分析参考数据。2023年度之前发布的两次报告&#xff0c;请参考&#xff1a; Backblaze发布2…

Vue-Pinia

目录 Pinia状态管理库 使用步骤 1、安装Pinia 2、在vue应用实例中使用pinia 3、在src/stores/token.js中定义stores 4、在组件中使用store axios请求拦截器 代码实现 Pinia状态管理库 Pinia是Vue的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态 一般在登录时…

第一百七十五回 如何创建放射形状渐变背景

文章目录 1. 概念介绍2. 实现方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在 上一章回中介绍了"如何创建扇形渐变背景"相关的内容&#xff0c;本章回中将介绍" 如何创建放射形状渐变背景"。闲话休提&#xff0c;让我们一起Talk Flutter吧…

根据店铺ID或店铺昵称或店铺链接获取阿里巴巴店铺所有商品数据接口|阿里巴巴店铺整店商品数据接口|阿里巴巴API接口

阿里巴巴店铺所有商品数据接口是阿里巴巴开放平台提供的API接口之一&#xff0c;它可以帮助开发者获取到店铺内所有商品的信息&#xff0c;包括商品的ID、标题、价格、图片、链接等。通过该接口&#xff0c;开发者可以快速地获取到大量的商品数据&#xff0c;并进行进一步的数据…

数字化时代,数据就是资产

2011年&#xff0c;麦肯锡发布报告&#xff0c;认为“大数据Big Data已成为当今竞争、创新、生产效率提升的关键基础”。一时间&#xff0c;大数据&#xff0c;成为业内热点。数据&#xff0c;大家都懂&#xff1b;大&#xff0c;有什么区别&#xff1f; 而不管大的是什么&…

centos的root密码忘记或失效的解决办法

目录 前言1 单机维护模式2 利用具有管理员权限的用户切换到root用户3 救援模式 前言 在Linux系统中&#xff0c;root用户是最高权限的用户&#xff0c;可以执行任何命令和操作。但是&#xff0c;如果我们忘记了root用户的密码&#xff0c;或者需要修改root用户的密码&#xff…

STM32中断看这一篇就够了

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 1. 前言…

ElasticStack日志分析平台-ES 集群、Kibana与Kafka

一、Elasticsearch 1、介绍&#xff1a; Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;Logstash 和 Beats 收集的数据可以存储在 Elasticsearch 中进行搜索和分析。 Elasticsearch为所有类型的数据提供近乎实时的搜索和分析&#xff1a;一旦数据被索引&#…

CUDA学习笔记8——GPU硬件资源

简单来说就是为了充分利用GPU&#xff0c;不要让分出去的CUDA核心摸鱼闲置&#xff1b;GPU每次干活&#xff0c;都是以最小的组分配的&#xff0c;因此分派任务的时候就尽量充分发挥每个小组里CUDA核心的作用。这里的每个小组就是一个SM&#xff08;stream multi-processor&…

所见即所得的动画效果:Animate.css

我们可以在集成Animate.css来改善界面的用户体验&#xff0c;省掉大量手写css动画的时间。 官网&#xff1a;Animate.css 使用 1、安装依赖 npm install animate.css --save2、引入依赖 import animate.css;3、在项目中使用 在class类名上animate__animated是必须的&#x…

hash路由模式

hash模式 hash模式是一种把前端路由的路径用井号 # 拼接在浏览器 URL 后面的模式。 一个完整的 URL 包括&#xff1a;协议、域名、端口、虚拟目录、文件名、参数、锚。 https://www.wangyuegyq.top/utils/index.html?name123&phone123#home协议&#xff1a;https域名&am…

3. hdfs概述与高可用原理

简述 HDFS&#xff08;Hadoop Distributed File System&#xff09;是一种Hadoop分布式文件系统&#xff0c;具备高度容错特性&#xff0c;支持高吞吐量数据访问&#xff0c;可以在处理海量数据&#xff08;TB或PB级别以上&#xff09;的同时最大可能的降低成本。 HDFS适用于…

大数据-之LibrA数据库系统告警处理(ALM-12049 网络读吞吐率超过阈值)

告警解释 系统每30秒周期性检测网络读吞吐率&#xff0c;并把实际吞吐率和阈值&#xff08;系统默认阈值80%&#xff09;进行比较&#xff0c;当检测到网络读吞吐率连续多次&#xff08;默认值为5&#xff09;超过阈值时产生该告警。 用户可通过“系统设置 > 阈值配置 >…

迈特优×实在RPA丨每年节省人天800+,企业自动化前后的区别如此大?

迈特优品牌设立于2015年&#xff0c;是一家集设计、生产、销售为一体的新电商企业&#xff0c;旗下拥有天猫、拼多多、唯品会等平台10余家店铺&#xff0c;在天猫男装品类排名前十&#xff0c;男装各个类目均有排名前五的商品&#xff0c;每年开发新品超过1000款。 为优化企业…

基于Vue+SpringBoot的无代码动态表单系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 动态类型模块2.2 动态文件模块2.3 动态字段模块2.4 动态值模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 动态类型表3.2.2 动态文件表3.2.3 动态字段表3.2.4 动态值表 四、系统展示五、核心代码5.1 查询档案类型5.…

μC/OS-II---进程间通信方式

目录 信号量&#xff08; Semaphores &#xff09;- 用于最基本的互斥、同步操作互斥信号量&#xff08;Mutual Exclusion Semaphores &#xff09;-专门用于互斥消息队列&#xff08; Message Queues &#xff09;- 用于消息通信消息邮箱&#xff08;Message Box&#xff09; …

Latex如何消除并自定义算法标识

正常&#xff1a; 修改后&#xff1a; 正常代码&#xff1a; \documentclass{article} \usepackage[ruled]{algorithm2e} \begin{document} \begin{algorithm} \caption{Hi} My name is XXX. \end{algorithm} \end{document}修改后代码&#xff1a; \documentclass{articl…