Linux相关概念和易错知识点(41)(UDP、TCP报头结构)

目录

  • 1.UDP
    • (1)传输层
    • (2)UDP报头
    • (3)缓冲区和sk_buff
      • ①缓冲区
      • ②sk_buff
  • 2.TCP
    • (1)发送和接受缓冲区
    • (2)报头结构
      • ①按序到达
      • ②可靠传输
      • ③流量控制
      • ④紧急指针


1.UDP

(1)传输层

UDP处在传输层(应用层之下,网络层之上),负责将数据从发送端传输到接收端。 其中我们已经知道:IP标识主机,端口号标识主机内的进程。因此,源IP、目的IP、源端口号、目的端口号、使用的运输层协议这五个元素(五元组)可以标识一个通信。

其中0 - 1023为知名端口号,和常见服务强绑定,如HTTP等。一个进程可以bind多个端口号,从多个端口接收数据,但一个端口号不能被多个进程bind,每个端口接收的数据只能上交给一个进程。

HTTP协议我们已经认识了,传输层协议本质也是一种约定,其底层实现是C语言。不仅如此,网络层、数据链路层都有自己的协议,OS内核各个模块的通信也有自己的协议。其中OS内核通信实现可以直接用二进制传输数据,无需做明显的序列化,并且效率高、兼容性好。

(2)UDP报头

和应用层一样,添加报头在逻辑上是在要传输的数据前后包装一些约定的对象,在代码上就是定义相应协议的结构体对象,调用功能函数把我们的数据和要添加的数据合并起来,这就是封装。

解析报头时,UDP直接读取收到的报文前8个字节,剩下就是有效载荷。报文的前8个字节包括:16位源端口号和16位目的端口号,16位当前UDP报文有效载荷长度(自描述字段),16位校验和。
由于记录了16位当前UDP报文有效载荷长度和16位校验和,因此报文会被完整合法地交给上层。如果出现了UDP检验和失败,那这个报文会被直接丢弃,而无需向接收方响应任何数据。

在这里我们要特别说明一下UDP是不可靠传输,不可靠在哪?16位当前UDP报文有效载荷长度,16位校验和都无法保证可靠性吗?UDP的不可靠之处在于如果数据不完整的话会直接丢弃,上层却不会知道这一切。而TCP就有自己的重传机制,会保证接收方一定会收到相同字节数的数据。

现在我们再次强调UDP三个特性的含义,以免混淆:
无连接意味着无需listen和connect;不可靠意味着没有确认和重传机制等;面向数据报意味着接收方必须 像收快递那样一次性必须全部把一个数据包传入应用层(不会出现粘包问题,只能一块一块地IO),而相对而言面向字节流就是以bit为单位的(这也是TCP需要序列化的根本原因)。

我们要消除一个误解,就是可靠和不可靠其实并不是优缺点,而是特性。TCP要做很多处理才能保证可靠传输,不可靠传输往往意味着协议会更简单。UDP在直播、视频领域很常用,因为一些丢包根本不影响,而像支付交易等才更需要TCP。

(3)缓冲区和sk_buff

①缓冲区

UDP封装在代码上就是创建相应的结构体对象,在创建时会同时申请一块缓冲区,就是UDP协议的缓冲区。UDP有接收缓冲区,但这个缓冲区接收的顺序不一定和对方发送的顺序一致,可能报文2比报文1先到,这也是不可靠的一种。相比而言TCP就没有这个情况,它会有序号保证数据的顺序性。当UDP接收缓冲区被写满后,再收到的数据会直接丢。

UDP没有也不需要发送缓冲区,UDP在收到应用层的数据后,会接添加报头直接往下传,而不需要做处理,但这不影响其全双工的特性。

②sk_buff

sk_buff是负责管理报文的结构体,它属于整个网络协议栈,即从链路层到应用层,始终是同一个sk_buff在管理这个报文。从面向对象的思想来看,我们可以认为对报文的管理就是对sk_buff的管理,这在后面理解缓冲区是sk_buff链表这件事上至关重要。

struct sk_buff 
{// 协议层头部指针__u16 transport_header;  // 传输层头部位置__u16 network_header;    // 网络层头部位置__u16 mac_header;        // 链路层头部位置//其余部分省略
};

当一个报文的sk_buff被创建后会由指针管理数据。通过修改指针指向就可以填充UDP报头字段,也就完成了UDP报头封装,其它协议也是这样。

单个UDP报文包含首部能传输的最大数据约为64k字节(MTU限制)。因此要传输更多数据,就要拆分报文,多次发送,多个报文由sk_buff组成的链表管理。UDP的接收缓冲区就是报文的sk_buff链表组成的。


2.TCP

(1)发送和接受缓冲区

TCP也有自己的缓冲区,且同时有发送接受缓冲区。当要发送时,数据会直接拷贝进缓冲区;当读取时,也会直接从接受缓冲区拷贝数据。而缓冲区就由OS自主决定什么时候发,什么时候收,和上层解耦。

我们前面已经提过,管理报文就是管理sk_buff,缓冲区是本应是char数组,但这样并不好处理。所以考虑以面向对象的思想来处理,TCP的发送/接受缓冲区和UDP的接受缓冲区都是sk_buff链表,从缓冲区读数据、写数据本质就是对sk_buff进行增删查改。

(2)报头结构

TCP的报头结构相对比较复杂,但就像在UDP说的,TCP之所以复杂是因为它需要实现一些特性,所以接下来我会根据TCP要实现的独特性质分类讲解报头结构,具体性质后续会拓展。

①按序到达

前面说过UDP不保证接收的顺序,而TCP需要。因此TCP需要给自己的每一个报文添加一个字段——32位序号。这样接收方就知道收到的数据属于哪个序号了。进一步,接收方也就知道现在还有哪些序号的数据没有收到了,这也能进一步实现可靠传输了。

需要注意的是,TCP中要传输的报文的每一个字节都有自己的序号,多个字节组成一个TCP报文,报头的序号就是起始报文对应的序号。

在这里又引入了一个问题:既然一个TCP报文有多个字节,而报头只记录第一个字节的序号,那么接收方怎么知道应该读多少字节呢?报文边界在哪呢?
首先我们要清楚,发送方从应用层接收数据,再创建对象封装,是肯定知道边界的,每个TCP数据段往下传的时候网络层也能分清,也就是说我们的疑惑来自于接收方。对于接收方来说,网络层解包后就会把整个数据交给TCP,这个时候TCP难道还不知道边界吗?网络层 -> 传输层交付的过程就已经有边界信息的交付了。

TCP报头中没有记录报文长度的字段,TCP可以借助其它层确认边界

但是这样还不够,接收方能够确认边界了,报文的边界呢?对于UDP来说,它的报头是固定长度8字节,而TCP有选项部分,可以多添加一些选项,所以TCP的报文长度相对更灵活,那么报文的起始位置就需要单独存储了,这就是——4位数据偏移,且偏移以4字节为单位。最小值5对应报文数据从20开始,报头占0 - 19共20字节;最大值15对应60字节的报头(TCP允许最多40字节的选项)

②可靠传输

下面的数据就是多个TCP报文,报头序号分别是1,1001,2001,3001,后续的例子都将建立在它之上。

有了序号之后就有机会实现可靠传输,具体过程是怎样的?
当发送序号为1的报文时,1 - 1000序号(共1000字节)的数据被发送和接收,接收报文之后接收方会发出一个回应,回应包含一个数字1001,告诉发送方1001之前的数据都收到了,这时发送方再从1001开始发送第二个报文,再回应,以此类推。这个回应中包含的确认的数字就是——32位确认序号。 如果此时报文2丢了,回应的就还是1001,那么这个时候发送方就会重传第2个报文。 但这样效率并不高,因此发送方会一直发送报文,而接收方收到一个报文就回应,回应中就能体现出丢没丢包,这样发送和回应就并行了。

有了确认序号之后,就能实现捎带应答机制了。从刚才的情况出发,发送方给接收方发报文,接收方通过确认序号回应,但如果回应时接收方发现自己想要给发送方再带一些消息,怎么办呢? 这个时候接收方就可以把要传的数据放在报文中,同时填充序号。这样发送方得到回应后,从序号处可以得到接收方想要给自己的数据,从确认序号那里也能得到确认信息,一举两得,这就是捎带应答机制。

捎带应答是一个可有可无的功能,比如接收方收到一个报文,它怎么知道这是一个单纯的应答,还是说有捎带应答?用序号和确认序号区分确实是一种方法,但是,TCP中这种可有可无的行为可不止捎带应答,还有一些后续会提及,所以 TCP报头需要集中管理,控制TCP连接的状态和数据传输行为,即6位控制位。

我们可以看到,当ACK == 1时,表示确认序号有效,这个时候接收方才会去解读确认序号。通过这张图可看出,控制位在TCP中非常重要,标识不同字段的有效性,算是给TCP报头进行一种分类了。

③流量控制

和UDP一样,TCP发送和接收缓冲区都是有大小的。UDP接收缓冲区满了就直接丢弃多的数据,TCP也是。但TCP要保证可靠传输,发送方发了多少数据要保证接收方能接收多少数据,这就意味着它需要尽可能避免这种情况,除了重传机制以外还要有流量控制,这就需要——16位窗口大小(0 - 65535字节)。

接收方和发送方进行TCP通信时,每个报头都要带上自己的窗口大小,就是自己的接受缓冲区的剩余的大小。 前面我说过发送方会连续发送多个报文,接收方再对接收的每个报文做回应,但是发送方在一定时间内连续发送报文数量的上限是什么呢?这就要引入滑动窗口了。 滑动窗口就是建立在TCP发送缓冲区之上的,是TCP决定什么时候从缓冲区向外发数据的关键结构。 滑动窗口大小的决定因素之一就是对方回应的16位窗口大小,滑动窗口大小不会超过16位窗口大小对应的值,这样就能保证发送方不会发送过多数据,以至于溢出接收方的接受缓冲区导致数据丢弃。

④紧急指针

TCP传输中,总会产生特殊情况需要紧急传输的数据,因此TCP还支持16位紧急指针(需要在控制位URG == 1时生效)。当紧急指针生效时,TCP按序到达就会被打破,OS优先读取处理紧急数据(如使用百度云盘,上传数据时用户申请终止上传,这个终止的指令就比较紧急,不需要等到前面大量数据被按序收到)。 紧急指针就是一个标记有效载荷中紧急数据的偏移量。紧急数据的长度呢?紧急数据只占1个字节,不能被大量使用。

其余部分,如端口、检验和等就不多赘述了,和UDP一致。

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

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

相关文章

光谱相机在生态修复监测中的应用

光谱相机通过多维光谱数据采集与智能分析技术,在生态修复监测中构建起‌“感知-评估-验证”‌的全周期管理体系,其核心应用方向如下: 一、土壤修复效能量化评估 ‌重金属污染动态监测‌ 通过短波红外(1000-2500nm)波…

[网页五子棋]项目介绍以及websocket的消息推送(轮询操作)、报文格式和握手过程(建立连接过程)

文章目录 项目背景核心技术创建项目WebSocket消息推送轮询操作 报文格式握手过程(建立连接过程) 项目背景 用户模块 用户的注册和登录管理用户的天梯分数,比赛场数,获胜场数等信息 匹配模块 依据用户的天梯积分,来实现匹配机制 对战模块 把两…

时序模型介绍

一.整体介绍 1.单变量 vs 多变量时序数据 单变量就是只根据时间预测,多变量还要考虑用户 2.为什么不能用机器学习预测: a.时间不是影响标签的关键因素 b.时间与标签之间的联系过于弱/过于复杂,因此时序模型依赖于时间与时间的相关性来进行预…

尚硅谷redis7 86 redis集群分片之3主3从集群搭建

86 redis集群分片之3主集群搭建 3主3从redis集群配置 找3台真实虚拟机,各自新建 mķdir -p /myredis/cluster 新建6个独立的redis实例服务 IP:192.168.111.175端口6381/端口6382 vim /myredis/cluster/redisCluster6381.conf bind 0.0.0.0 daemonize yes protected-mode no …

Python服务器请求转发服务

前言: 服务器无法连接外网 配置步骤 准备python脚本服务器内下载python 示例 1.下载python创建虚拟环境以及配置 -- 磁盘空间 df -h -- 下载apt sudo yum install apt -y-- 下载python pip sudo apt install python3 python3-pip python3-venv -y-- 测试查看 …

02.K8S核心概念

服务的分类 有状态服务:会对本地环境产生依赖,例如需要把数据存储到本地磁盘,如mysql、redis; 无状态服务:不会对本地环境产生任何依赖,例如不会存储数据到本地磁盘,如nginx、apache&#xff…

Java八股-Java优缺点,跨平台,jdk、jre、jvm关系,解释和编译

java优势劣势? 优势:面向对象,平台无关,垃圾回收,强大的生态系统 劣势:运行速度慢(相比于c和rust这样的原生编译语言会比较慢),语法繁琐(相比于python&…

Attention Is All You Need论文阅读笔记

Attention is All You Need是如今机器学习研究者必读的论文,该文章提出的Transformer架构是如今很多机器学习项目的基础,说该文章极大推动了机器学习领域的研究也不为过。 但这么重要,也是必读的文章对初学者来说其实并不友好,很多…

【MAC】YOLOv8/11/12 转换为 CoreML 格式并实现实时目标检测

在本文中,我们将详细介绍如何将 YOLOv8/11/12 模型转换为 CoreML 格式,并使用该模型在摄像头实时检测中进行目标检测。主要适用于M1、M2、M3、M4芯片的产品。 以下教程在YOLOv8/11/12均适用,此处就以 YOLOv11 举例 目录 前提条件YOLOv8/11/12 转换为 CoreML实时目标检测结论…

Redis--缓存击穿详解及解决方案

缓存击穿 缓存击穿问题也称热点key问题,就是一个高并发访问(该key访问频率高,访问次数多)并且缓存重建业务比较复杂的key突然失效了,大量的请求访问会在瞬间给数据库带来巨大的冲击。 缓存重建业务比较复杂&#xff…

UniApp X:鸿蒙原生开发的机会与DCloud的崛起之路·优雅草卓伊凡

UniApp X:鸿蒙原生开发的机会与DCloud的崛起之路优雅草卓伊凡 有句话至少先说,混开框架中目前uniapp x是率先支持了鸿蒙next的开发的,这点来说 先进了很多,也懂得审时度势。 一、UniApp X如何支持鸿蒙原生应用? UniAp…

域名解析怎么查询?有哪些域名解析查询方式?

在互联网的世界里,域名就像是我们日常生活中的门牌号,帮助我们快速定位到想要访问的网站。而域名解析则是将这个易记的域名转换为计算机能够识别的IP地址的关键过程。当我们想要了解一个网站的域名解析情况,或者排查网络问题时,掌…

算力卡上部署OCR文本识别服务与测试

使用modelscope上的图像文本行检测和文本识别模型进行本地部署并转为API服务。 本地部署时把代码中的检测和识别模型路径改为本地模型的路径。 关于模型和代码原理可以参见modelscope上这两个模型相关的页面: iic/cv_resnet18_ocr-detection-db-line-level_damo iic…

大语言模型的完整训练周期从0到1的体系化拆解

以下部分内容参考了AI。 要真正理解大语言模型(LLM)的创生过程,我们需要将其拆解为一个完整的生命周期,每个阶段的关键技术相互关联,共同支撑最终模型的涌现能力。以下是体系化的训练流程框架: 阶段一&am…

吃水果(贪心)

文章目录 题目描述输入格式输出格式样例输入样例输出提交链接提示 解析参考代码 题目描述 最近米咔买了 n n n 个苹果和 m m m 个香蕉,他每天可以选择吃掉一个苹果和一个香蕉(必须都吃一个,即如果其中一种水果的数量为 0 0 0,则…

【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(4)

1.问题描述: LoginWithHuaweiIDButton不支持深色模式下定制文字和loading样式? 解决方案: LoginWithHuaweiIDButtonParams 中的有个supportDarkMode属性,设置为true后,需要自行响应系统的变化,见文档&am…

【C语言】指针详解(接)

前言: 文接上章,在上章节讲解了部分指针知识点,在本章节为大家继续提供。 六指针与字符串:C 语言字符串的本质 在 C 语言中,字符串实际上是一个以\0结尾的字符数组。字符串常量本质上是指向字符数组首元素的指针&…

第5讲、Odoo 18 CLI 模块源码全解读

Odoo 作为一款强大的企业级开源 ERP 系统,其命令行工具(CLI)为开发者和运维人员提供了极大的便利。Odoo 18 的 odoo/cli 目录,正是这些命令行工具的核心实现地。本文将结合源码,详细解读每个 CLI 文件的功能与实现机制…

如何将 PDF 文件中的文本提取为 YAML(教程)

这篇博客文章将向你展示如何将 PDF 转换为 YAML,通过提取带有结构标签的标记内容来实现。 什么是结构化 PDF? 一些 PDF 文件包含结构化内容,也称为带标签(tagged)或标记内容(marked content)&…

银发团扎堆本地游,“微度假”模式如何盘活银发旅游市场?

​ 银发微度假,席卷江浙沪 作者 | AgeClub吕娆炜 前言 均价200-300元的两天一夜微度假产品,正在中老年客群中走红。 “我们属于酒店直营,没有中间商赚差价,老年人乘坐地铁到目的地站,会有大巴负责接送,半…