【TCP/IP】确认应答、超时重传机制和TCP报头

news2024/9/27 17:25:40

TCP 相关机制

TCP 基本特点:有连接、可靠传输、面向字节流、全双工

  • 有连接、面向字节流和全双工都能在前面的代码中体现
  • 有连接:必须要先调用 accept 建立联系才能处理
  • 面向字节流:会拿到 clientSocket 对象的 InputStreamOutputStream,再来去读写数据
  • 全双工:一个 Socket 对象,既可以读,也可以写
    而此处的可靠传输在代码层面感知不到,它是在系统内核完成了这里的工作

TCP 最核心的资质就是“可靠传输”,不能做到 100% 送达,只能尽可能的是数据能到达对方方

  1. 能感知到对方是否收到
  2. 如果发现对方没有收到,就要进行重试

后发先至

image.png

  • 如果数据按照左边的传输次序来的,那就不会有歧义
  • 虽然女神先发的“好啊好啊”,后发的“滚”,但是在网络传输中,可能存在“后发先至”,对于我们接收方来说,可能会先收到“滚”,后收到“好啊好啊”
  • 此时,歧义就产生了,我将会误以为女神答应我了

出现原因

互联网最初是用来防御核弹打击的,即使是遭受到了核弹打击,但是 A~B 之间的通信路径有很多很多条,不会全军覆没,所以仍然可以确保数据能正常传输

  • 在正常传输数据的时候,传输数据包不一定走同一条路线
  • 因为是不同的路线,每个数据包传输过程中,遇到的状况也都有差别,最终达到目标的时序就可能存在差异了

举个例子:一个婚车队伍,在触发的时候都是按照顺序,一辆一辆跟着走的,但一到大路上,车队就可能会走散

  • 本来跟着头车走,结果遇到了红灯,一旦跟不上,就各凭本事了
  • 每辆车,各个导航,可能走的路线都不一样,可能有的车还会堵车
  • 最后到达目的地的先后顺序改变的情况就是很常见的

1. 确认应答

后发先至的解决方法,TCP 核心机制,感知对方是否收到,就是要靠对方告诉你一声“收到了”

  • 后发先至是客观存在的情况,无法改变
    若要解决,可以给传输的数据添加“编号”,通过编号,可以区分出数据的先后顺序
    image.png|448
  • 我收到的应答报文,即使顺序出现错乱,也能识别出来原意
  • 由于 TCP 是面向字节流的,是加上这里的编号并非是按照“第一条,第二条”这样的方式来编排的,而是按照“字节“,“第一个字节,第一百个字节”,这样来编排的
  • 每个字节都有一个独立的编号,字节和字节之间,编号是连续的、递增的
  • 这种按照字节编号的机制,就成为“TCP 的序号”,在应答报文中,针对之前收到的数据进行对应的编号,称为“TCP 的确认序号

之后,TCP 就可以针对接收方收到的信息,进行重新排序,确保应用程序 read 到的数据一定是和发送方的数据顺序是一致的

image.png|482
接收方这边调用 read 的时候如果没有数据,就会阻塞等待(前面回显服务器文章中写的是 scanner 读取,本质上就是调用 InputStream.read

  • 接收方收到的数据信息顺序可能和发送发传输时的顺序不一样
  • 此时接收方收到 1001-2000 这个数据到了,但是接收方不会让 read 接触阻塞,因为这个数据的起始部分还没到,2001-3000 到了之后也进行阻塞
  • 直到 1-1000 这个数据到达之后,read 才会接触阻塞,才会读取到 1-10001001-20002001-3000
    • 接收方这边,操作系统内核里面,有一段空间,作为“接收缓冲区”,收到的数据就会先在缓冲区中排队等待,直到开头的数据到了,应用程序才能真正读取到里面的数据

前面接亲的例子:等婚车到了女方门口,因为头车还没来,所以不能直接开到新娘门口去接人

  • 因此这样的车就得在外等待,必须等头车到
  • 等车到了之后,再重新排好队,再一起开到新娘家门口

丢包

丢包的原因有很多种:

  1. 数据传输的过程中,发生了 bit 翻转,收到这个数据的接收方/中间的路由器什么的,计算校验和,但是发现校验和对不上
    发现错误,要及时止损,不能将错就错
  • 所以就会把这个数据丢弃掉,不继续往后转发/不交给应用层使用

  1. 数据传输到某个节点(路由器/交换机),但这个节点的负载太高了,后续传输过来的数据就可能被这个路由器直接丢弃
    • 负载太高:某个路由器,单位时间只能转发 N 个包,但现在是网络高峰期,这个路由器单位时间需要转发的包超过 N 个了,发不过来了

2. 超时重传

发生丢包是完全随机,不可预测的,TCP 再怎么厉害,也不可能避免数据发生丢包。TCP 能做的是:感知到数据是否丢失,如果丢包,就重新再发一次

此时需要通过应答报文来区分

  • 收到应答报文,说明数据没丢包
  • 没收到应答报文,就说明数据丢包了
    • 网络传输是需要消耗时间的,这里的“没收到”是暂时没收到,还是永远都收不到?
    • 发送方发送数据之后,会给出一个“超时时间”,如果在这个时间限制之内,没有收到反馈的 ACK(应答报文 ACK 由 0 变为 1),就视为数据丢包了
      image.png|518
      不管是因为数据丢了导致的丢包还是因为 ACK 丢了导致的,都会重发
  • 但如果是因为 ACK 丢了导致的重发,接收方就会收到两份一样的数据,这样是很不好的(一次扣款请求扣两次)
  • 所以为了确保应用程序调用 read 读出来的数据是唯一、不重复的,TCP 就会对这种情况进行处理——去重
    • 接收方有一个“接收缓冲区”,收到的数据会先进入到缓冲区里,后续再督导数据,就会根据序号,在缓冲区中找到对应的位置(排序)。如果发现当前序号 1-1000 这个数据已经在缓冲区中存在了,就会直接把新收到的这个数据丢弃掉

超时时间的设定

这里的时间不是固定不动的,而是动态变化的
发送方第一次重传,超时时间是 t1,如果重传之后,仍然没有 ACK,就会继续重传,第二次重传的超时时间是 t2t2>t1

  • 每多重传一次,超时时间的间隔就会变大,重传的频次会降低
  • 经过一次重传之后,就能让数据到达的概率提升很多
  • 反之,如果重传了几次,都没有顺利到达,说明网络的丢包率已经达到了一个非常高的程度——>网络发生了严重故障,大概率没法继续使用了
    重传也不会无休止的进行,当重传达到一定次数之后,TCP 不会再重传,就认为这个连接已经挂了
  • 先尝试进行“重置/复位连接”,发送一个特殊的数据包“复位报文”,尝试和对方重新进行连接
  • 如果网络这会恢复了,复位报文就会重置连接,使通信可以继续进行
  • 如果网络还有严重问题,复位报文也没有得到回应,此时 TCP 就会单方面放弃连接(发送方释放掉之前接收方的相关信息,这个连接诶也就没了)

确认应答和超时重传相互补充,共同构建了 TCP 的“可靠传输机制

  • 可靠传输机制不是靠“三次握手和四次挥手保证的”

TCP 报头

image.png|449

首部长度

TCP 报头的长度

  • UDP 协议报头固定就是 8 个字节
  • 对于 TCP 来说,报头长度是可变的
    4 个比特位可表示的范围:
  • 0000~1111——>0x0~0xF——>0~15
  • 此处的长度单位是 4 字节,不是字节(所以范围是 0~60 字节)

保留(6 位)

虽然现在不用,但是先把这个东西申请下来,以备不时之需。用于考虑未来的可扩展性

  • 充分吸取了 UDP 的教训,UDP 的报文长度字段,是没法扩展的
  • 如果未来某一天,TCP 需要新增属性或者谋和属性的长度不够用,就可以把保留位拿出来,进行使用
  • TCP 的结构不需要发生太大的改变,这样的升级就会容易很多

关于“可扩展性”也是属于编程的时候需要考虑到的一点,毕竟写的代码不可能写一份就能持续地使用。对代码做出调整,做出修改,是非常普遍、常见的情况
但是,

选项

TCP 报头边长的主要原因。四个字节为一个单位

  • 可以有, 也可以没有
  • 可有一个,也可有多个
    通过“首部长度”确定报头有多长,如果是两个四个字节长度就是两个选项,三个四个字节长度就是三个选项,以此类推

序号

由于会出现“后发先至”的情况,所以需要通过编号,区分出数据的先后顺序
序号:表示的就是 TCP 数据报载荷中的第一个字节的序号,由于序号是连续递增,知道了第一个字节的序号,后续每个字节的序号也就知道了
image.png|565

  • 32 位/四字节,表示的范围是 0~42亿9千万0~4G
  • 因为 TCP 是面向字节流的,所以一个 TCP 数据报和下一个 TCP 数据报携带的数据,是可以直接进行拼装的
  • 比如要传输一个特别大的数据,传输过程中,本身就会通过多个 TCP 数据报来进行携带,这些 TCP 数据报彼此之间携带的载荷都是可以在接受方自动拼起来的
    • 这样就不像 UDP 存在传输的上限,使用 UDP 传输大数据,就需要考虑调用这一次 send 操作,参数是否超过了 64KB,超过了就不行
    • 使用 TCP 的话就没关系,可以调用一次 write,也可以调用多次 write。无论怎么进行 write,在网络传输和对端接收的角度来看是没有任何差别的
    • 如果多次 write,传输的总数据量超过上述的 4G 也没关系,这里的数据序号是可以再从 0 开始重新设置的

确认序号

确认序号的设定方式,和后发先至中发短信的例子,略有差别

  • TCP 序号不是按照“一条两条”来编排的,而是按照“字节”来编排的
    image.png|357

TCP 的确认序号这里,填写的是 1001,接收方收到的数据的最后一个字节序号的下一个序号

  • 表示的含义是 <1001 的序号的数据都收到了(TCP 序号是连续增长的)
  • 对于应答报文来说,“确认序号”就会按照收到的数据的最后一个字节序号+1 的方式来填写
  • 并且六个标志位中,第二个标志位(ACK)会设为 1
    • 普通报文的 ACK0,应答报文的 ACK1
    • 如果是普通报文,序号是有效的,确认序号是无效的;如果是应答报文,序号和确认序号都是有效的
    • 应答报文的序号是另一套编号体系,和传输数据的序号是不一样的
    • 应答报文默认情况下是不携带数据的

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

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

相关文章

[书生大模型实战营][L0][Task2] Python 开发前置知识

0. 任务&#xff1a;在 InternStudio 环境中实现功能&#xff1a; python 实现 wordcount函数&#xff0c;统计英文字符串单词的使用频率&#xff0c;并返回字典&#xff1b;vscode 远程调试 InternStudio 中的 python 代码 1. wordcount 函数实现 string.punctuation 是一个…

从【人工智能】到【计算机视觉】,【深度学习】引领的未来科技创新与变革

前几天偶然发现了一个超棒的人工智能学习网站&#xff0c;内容通俗易懂&#xff0c;讲解风趣幽默&#xff0c;简直让人欲罢不能。忍不住分享给大家&#xff0c;点击这里立刻跳转&#xff0c;开启你的AI学习之旅吧&#xff01; 前言 – 人工智能教程https://www.captainbed.cn/l…

CentOS迁移案例 | 保障轨道交通安全、发挥基础设施效能,麒麟信安操作系统支撑某市轨道交通畅行无忧

为缓解城市交通拥堵难题&#xff0c;某市轨道交通公司计划新建一条贯穿城市关键区域、沿路设立20座站点的轨道交通线路&#xff0c;并基于麒麟信安操作系统构建轨道交通信号系统。 轨道交通信号系统是列车核心控制系统&#xff0c;负责列车运行的自动化控制&#xff0c;及对整…

【python】python代码打包工具cx_Freeze的介绍、原理、用法及实战案例分析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

学习机MP3语音芯片方案:WMV硬解码芯片,N9301-316

在当今数字化时代&#xff0c;学习机已不再仅仅是静态的物品。随着技术的快速发展和不断探索创新方法&#xff0c;人们将音乐与互动学习相融合&#xff0c;为儿童创造出更加富有创意和学习机产品。其中&#xff0c;九芯电子N9301系列MP3解码芯片在这一领域的应用正在崭露头角&a…

Android常见控件(一)

目录 前言 一、TextView控件 常用属性 二、Button控件 设置点击事件的方式 1.在布局文件中指定onClick的值 2.使用匿名内部类 3.通过实现onClickListener接口 三、ImageView控件 常见属性 src与background的区别 scaleType 1.ScaleType.FIT_CENTER默认 2.ScaleTy…

Java学习高级五

API 常用API Object类 Object类的常见方法

数据结构与算法 - 双指针

一、移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12]输出: [1,3,12,0,0]示例 2: 输入: nums …

Linux文件传输命令介绍(非常详细)零基础入门到精通,收藏这一篇就够了

文件传输命令 1 ftp&#xff1a;传统的文件传输协议,使用广泛但安全性较低。 sftp&#xff1a;基于SSH的安全文件传输协议,提供交互式的文件管理功能。 tftp&#xff1a;简单的文件传输协议,主要用于网络设备的固件升级。 lftp&#xff1a;功能强大的FTP客户端,支持多种文件…

2024最新外卖霸王餐小程序系统源码|霸王餐美团/饿了么系统 粉丝裂变+私域运营+持续稳定

前言&#xff1a; 外卖霸王餐小程序是一种结合了外卖点餐和优惠返利功能的微信小程序&#xff0c;为用户提供了一种便捷的点餐体验和优惠福利。 一、霸王餐系统小程序是什么&#xff1f; 霸王餐系统是指一种特殊的营销活动平台&#xff0c;商家通过该平台提供免费或大幅度折…

【深度学习】嘿马深度学习笔记第3篇:TensorFlow介绍,学习目标【附代码文档】

本教程的知识点为&#xff1a;深度学习介绍 1.1 深度学习与机器学习的区别 TensorFlow介绍 2.4 张量 2.4.1 张量(Tensor) 2.4.1.1 张量的类型 TensorFlow介绍 1.2 神经网络基础 1.2.1 Logistic回归 1.2.1.1 Logistic回归 TensorFlow介绍 总结 每日作业 神经网络与tf.keras 1.3 …

Netty深度剖析(2)— 事件调度

我们在上一节已经简单的介绍了一下 Netty 的事件调度&#xff0c;可以说 Netty 高性能的奥秘主要就在于其核心的事件循环和任务处理引擎&#xff0c;那么它究竟是如何实现的呢&#xff1f;这一节我们来详细探讨一下 Reactor 线程模型 在解释 Netty 事件循环的实现原理前&#…

C语言enum枚举

目录 开头1.什么是枚举?2.枚举的优缺点优点缺点 3.枚举的实际用途(这里只列举其一)简易计算器枚举版…… 结尾 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们要学关于C语言枚举的一些知识。 1.什么是枚举? 枚举&#xff0c;就是一一列举的意思&#xff0c;比…

Verilog刷题笔记53

题目&#xff1a; Fsm serialdata See also: Serial receiver Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs …

Identity IdCard OCR API 对接说明

Identity IdCard OCR API 对接说明 本文将介绍一种通过输入身份证图片 或 姓名和身份证号码&#xff0c;来校验姓名和身份证号的真实性和一致性。本接口用于校验姓名和身份证号的真实性和一致性&#xff0c;您可以通过输入姓名和身份证号或传入身份证人像面照片提供所需验证信…

消息系统-WebSocket消息推送

消息系统-WebSocket消息推送 接口层使用消息通知 1.数据库设计: 1.消息通知表 2.消息记录表 3.用户表和角色表及用户角色记录表 2.设计: 未使用消息中间件 ,利用接口层调用消息通知接口工具类 3.前端:消息通知页面 1.消息通知列表 2.消息通知标签 3.消息通知未读抽屉列表 一.…

【C#】虚部与实部

实数是数学中的一个基本概念&#xff0c;它包括了所有的有理数和无理数。实数集合是连续的&#xff0c;可以表示为数轴上的每一个点。 复数是实数的扩展&#xff0c;它允许进行除零以外的所有基本算术运算。复数由两部分组成&#xff1a;实部和虚部。 实部&#xff08;Real P…

计算机毕业设计选题推荐-springboot 基于SpringBoot的家电销售展示平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

迪杰斯特拉(Dijkstra)算法(C/C++)

迪杰斯特拉&#xff08;Dijkstra&#xff09;算法是一种用于在加权图中找到单个源点到所有其他顶点的最短路径的算法。它是由荷兰计算机科学家艾兹格迪科斯彻&#xff08;Edsger Dijkstra&#xff09;在1956年提出的。Dijkstra算法适用于处理带有非负权重的图。迪杰斯特拉算法主…

k8s上部署ingress-controller

一、安装helm仓库 # helm pull ingress-nginx/ingress-nginx 二、修改 三、运行 # kubectl label nodes node01.110111.cn ingresstrue# kubectl label nodes node02.110112.cn ingresstrue# helm upgrade --install ingress-nginx -n ingress-nginx . -f values.yaml 四、检…