传输层协议之UDP

news2024/9/20 14:47:45

1、端口号

        我们在应用层创建的套接字,是需要通过bind()接口绑定我们的IP地址与端口号的,这是因为数据从传输层向上交付到应用层时,需要用端口号来查找特定的服务进程。一般在网络通信时,用IP地址标识一台主机,用端口号表示该主机上特定的服务。所以一台主机上,可能同时存在各种不同的服务,每一种服务都有它对应的端口号。在传输层,系统会根据我们的端口号找到应用层的进程,将我们的数据交给应用层。所以网络通信最后实际上是把数据包向上根据端口号交付给特定进程。在TCP/IP协议中,使用五元组(源IP、源端口、目的IP、目的端口、协议号)保证通信中进程的一对一。

        端口号的是16位无符号整数,所以取值范围应该是0~65535,实际上在使用云服务器时,我们在bind()时,会发现有时候bind不了,因为在云服务器中的一些端口号是知名端口号,我们熟知的HTTP、FTP、SSH这些广泛使用的应用层协议,它们有自己的端口号,一般是固定不变的,被业界广泛承认固定,所以我们无法绑定这些端口号。知名端口号范围是0~1023,从1024~65535才是操作系统动态分配的端口号,一般客户端在随机分配端口的时候,是从这个范围中分配的。

        有两个问题,(1)一个进程能否绑定多个端口号?(2)一个端口号能否被多个进程绑定?答案分别是可以和不可以。数据在交付时,通过网络分层,一定是自底向上进行交付的,所以一定要保证从端口号到进程的唯一关系。而一个进程绑定多个端口号其实不破坏端口号到进程的唯一关系,所以是可以的。举个例子,我们可以写一个服务器,他有一个80号端口使用TCP协议,我们为其创建一个套接字,我们在创建一个使用UDP协议的套接字,绑定81号端口,在网络通信时既可以使用80号端口也可以使用81号端口,它们都与一个进程绑定,可以用不同的端口提供不同的服务,比如使用UDP端口发指令,使用TCP端口发数据。

UDP

1、报文格式        

        下面这张图就是UDP报文的格式分布,最下面有一个数据,代表应用层向下交付的所有数据,也成为UDP报文的有效载荷。所以我们在应用层使用套接字和sendto接口发送数据时,并不是直接讲数据发送到网络中去,而是发给了传输层,UDP协议会为我们的有效载荷进行添加报头封装,形成完整的UDP报文,进而进一步向下交付。

        具体来看,UDP报头里面包含16位源端口,16位目的端口,16位UDP长度和16位UDP校验和。在我们进行应用层代码编写时,写套接字时,我们绑定端口号为什么一定要使用uint_16?因为传输层和网络层时是属于操作系统内容,是由Linux内核进行管理的,在操作系统内部,端口号使用16位来表示的,这就决定了我们在应用层也要使用16位进行设置。16位校验和是UDP保证数据基本的正确性的一种策略。

        那么UDP报文在传输层是如何做封装和解包的?大部分的应用层协议为了让报头和有效载荷分离,要么规定特殊符号,比如\r\n来标识报头和有效载荷,要么直接在报头设置文件描述字段,比如在自己的报文前面带上长度。在UDP这里是怎么实现的呢?非常简单,UDP采用的策略叫做定长报头,传输层如果发现接收到的报文是一个UDP报文,内核中会直接把报文的前八个字节移走,移走之后再把有效载荷向上交付就可以了。这种策略可以说是所有协议中,设计最简单的,大小固定,在收发通信时,报头长度永远都是固定的,报头一旦固定约定好,客户端和服务器都认为报头是八个字节,所以再封装的时候加八个字节,解包的时候提取前八个字节,剩下的都是有效载荷。

        传输层上面还有很多的应用层协议(包括http、https、ssh),在传输层解包之后,后续的行为叫做对报文分用,什么是分用?是指传输层把报头和有效载荷分开之后,将有效载荷交给上层的特定协议。如何实现分用?报头中有16位目的端口号,系统根据目的端口号找到特定的进程,也就是应用层协议,将有效载荷向上交付,报文在向上交付到指定进程这个行为,其实就是交付到指定的应用层协议,可以认为应用层协议、进程、端口号是三位一体的

        我们可以看到报头中有一个字段叫做16位UDP长度,这个长度代表整个UDP报文的长度(包含报头),这也就意味着整个UDP报文的最大长度是2的16次方,也就是64kb,在当前的网络环境中,64kb其实是一个很小的数据量,如果我们要在传输层使用UDP协议传输大于64kb的数据,我们必须要在应用层将报文拆成64kb一下的数据,不然会发送失败。

        

2、UDP的特点

        (1)无连接。我们使用UDP协议实现一个服务器与客户端通信功能时,客户端建立套接字,bind自己的ip地址和端口号,并知名目的端口和ip,就可以直接发送消息,就像我们发送邮件时,是不需要确认自身与接收方的连接关系的。不像TCP在正式通信之前要经过三次握手确认两端已经连接好了才能发送数据。

        (2)不可靠。不论任何协议,在数据传输过程中可能发生丢包问题,一个报文在路上要经过无数个主句,无数个路由器,无数个转发设备进行转发,所以丢包其实是一个很常见的情况。关键在于不同的协议面对丢包的处理方式不同,UDP协议下,丢包了之后什么都不做,这就是所谓的不可靠。而TCP为了保证可靠性设计了一系列策略,超时重传、连接管理、流量控制、拥塞控制等。

        (3)面向数据报。首先,面向数据报我们可以类比为收发快递,当商家给我们发送三个快递,我们一定是要收三个快递的,不能只收一个或者一个半或者五个,不存在我们取快递时先取走半个,下次再取后半个,必须整发整取。在实际代码层面,服务器接收客户端报文,调用recvfrom接口时,要么别读,要么调用recvfrom成功时,必定读取到一个完整的报文,客户端发了十个报文,代表其调用了10次sendto接口,服务端也必须调用10次recvfrom接口,这个次数是一比一的(在不考虑丢包的前提下)。所以在写代码时,在UDP协议下,读取报文时不需要验证读取报文的完整性的,读取到报文之后只需要考虑数据的序列和反序列化(结构化)问题就可以了,而在TCP协议下,基于其面向字节流的特性,我们在应用层还需要设置一些验证报文完整性的策略。

        这里讲讲面向字节流,它的特点就是,发送端发数据可能发了十几二十次,但是接收方并不知道发送端发了多少次,上层也不知道报文与报文之间在传输层有什么样的边界,发了十多次,接收方可能一次就把数据读完了,也可能100次才读完。至于如何保证读取报文的完整性,程序员需要在应用层自己去定协议,自己从字节流中提取一个完整的报文。

3、UDP的缓冲区

        在讲UDP的缓冲区之前,先通过了解TCP的缓冲区对传输层缓冲区有一个系统的了解。

        这一段所讲的全部都是在TCP协议下的。在应用层我们调用的对套接字进行操作的接口,诸如read、write、send等等,我们在调用这些接口时并没有把数据从应用层,直接发送到网络里,我们只是通过这样的接口把数据交给了下层传输层,然后再继续向下交付。需要明确一点,我们用的这些网络IO接口,其实并不是直接发送,而是拷贝接口。在TCP这样的协议下,实际上通信双方会在各自的传输层维护发送和接收缓冲区,客户端和服务器都有,在调用send和write接口时,我们应用层中也要维护一块缓冲区,也许是一个char buffer[1024],我们从标准输入流中拿到数据也需要先保存到应用层的缓冲区中,接着调用send和write时,我们并没有直接将数据发送到网络中,而是把应用层的数据拷贝到自己的发送缓冲区中。拷贝好了之后,再由传输层,也就是操作系统,来控制发送缓冲区里的数据什么时候发?发多少?最终经过网络把数据放到对方的接收缓冲区里了。客户端读取时,也并不是从网络里读取上来,而是从接收缓冲区把数据拷贝到应用层中。TCP协议下,通信双方都维护了自己的发送缓冲区和接收缓冲区,可以同时实现两个方向的数据流动,互不干扰,这样的通信方式,称之为全双工。当应用层通过调用send或者write接口把数据交付给TCP之后,接口就直接返回了,相当于数据交付给了操作系统,后续什么时候发,发多少,丢包了怎么办,由操作系统来自主地决定(这也是为什么TCP叫做传输控制协议),应用层可以继续进行后续的业务,所以传输层缓冲区存在的价值,除了支撑全双工,还能够直接提高我们发送数据的效率。总而言之,用户把数据从应用层拷贝到对应的操作系统内部,操作系统再把数据从缓冲区刷新到网络里,有人放有人取,这个模型特别像之前提过的生产消费者模型,也是发送端和接收端进行解耦,解决忙闲不均问题。

        以上就是我们的传输层缓冲区的概念,可以联想到我们使用系统调用读写文件,我们基于文件描述符对文件进行读写,调用write时并不是把数据直接写到了磁盘上,因为IO太费时间了,调用write只是将数据拷贝到内核维护的一块缓冲区中,系统会等到数据到达一定数量或者读到\n再把数据刷新到磁盘上。

        现在来谈谈UDP,其实UDP没有真正意义上的发送缓冲区,它不需要发送缓冲区,应用层的数据交付到传输层,UDP直接添加上所谓的报头,直接交给在下一层,它不用支持可靠性机制,所以不需要暂时把数据暂存下来。我们应用层调用sendto把数据交给操作系统操作系统将数据传输给网络层,之后进行后续的传输动作。而UDP是具有接收缓冲区的,用于保存收到的数据,本质上,也是为了应对传输层收到数据了,而应用层还在对上一次接收到的数据进行处理而来不及接收的问题。这个接收缓冲区不保证数据有序,即不保证接收到的数据和发送的数据顺序一致,乱序本身是不可靠的一种情况。如果缓冲区中的数据满了,后续的数据会直接丢弃,这时UDP的处理策略。UDP整体上是支持通信双方同时读写的,因此它也具有全双工的特点。

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

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

相关文章

查找PPT中某种字体的全部对应文字

本文章的目的是找到某种字体的文字,而不是替换某种字体的文字,也不是将某种字体全部替换为另外一种文字。 第一步:在PPT中按下ALTF11 出现以下窗口 第二步:点击插入->模块 第三步:将以下代码输入到窗体中 Sub F…

【备战秋招】——算法题目训练和总结day4

【备战秋招】——算法题目训练和总结day4😎 前言🙌Fibonacci数列我的题解思路分享代码分享 单词搜索我的题解思路分享代码分享 杨辉三角我的题解思路分享代码分享 总结撒花💞 😎博客昵称:博客小梦 😊最喜欢…

C++的缺省参数、函数重载和引用

缺省参数 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参 则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。(有些地⽅把 缺省参数也叫默认参数),要注意的是…

相对位移(鼠标)和绝对位移(触摸屏)

引言 EV_REL 表示相对位移(比如鼠标), EV_ABS 表 示绝对位置(比如触摸屏) 为什么鼠标是相对位移,触摸屏绝对位置? 总结 在Linux操作系统中,输入设备如鼠标和触摸屏通过事件设备接口(Event Device Interface)来与系统交互。这个接口定义了一…

java《字符串基础篇》--字符串全套知识点总结及其配套习题逐语句分析(附带全套源代码)

一、前言 从今天开始就要学习字符串了,java中的字符串和其他编程语言的有些许不同,不过大家也不必担心,基本的原理都是相同的,只是代码的实现有些许差异,问题不大。对于字符串习题方面都是些最基础的题目,…

Matlab结合ChatGPT—如何计算置信区间?

​前面分享了带置信区间的折线图和带置信区间的折线散点图的绘图教程: 很多人表示,昆哥,图是很好看啦,但咱不会求置信区间啊,咋办嘞? 说实话,这种事情属于数据处理,一般都是在画图前…

Hadoop3:HDFS-通过配置黑白名单对集群进行扩缩容,并实现数据均衡(实用)

一、集群情况介绍 我的本地虚拟机,一共有三个节点,hadoop102、hadoop103、hadoop104 二、白名单 创建白名单文件whitelist,通过白名单的配置,只允许集群包含102和103两台机器可以存储数据,104无法存储数据。 需求 …

CSS实现超链接标签:鼠标光标为手形、取消下划线、当鼠标悬停时显示下划线

1、鼠标光标为手形 cursor: pointer; 2、显示/取消下划线 text-decoration: none; /* 文本取消下划线 */ text-decoration: underline; /* 文本添加下划线 */ 3、伪类选择器 伪类选择器是 CSS 中已经定义好的选择器,因此程序员不能随意命令。伪类选择器…

深度学习DeepLearning二元分类 学习笔记

文章目录 类别区分变量与概念逻辑回归Sigmoid函数公式决策边逻辑损失函数和代价函数逻辑回归的梯度下降泛化过拟合的解决方案正则化 类别区分 变量与概念 决策边置信度阈值threshold过拟合欠拟合正则化高偏差lambda(λ) 线性回归受个别极端值影响&…

ElasticSearch 深度分页详解

原文链接:https://zhuanlan.zhihu.com/p/667036768 1 前言 ElasticSearch 是一个实时的分布式搜索与分析引擎,常用于大量非结构化数据的存储和快速检索场景,具有很强的扩展性。纵使其有诸多优点,在搜索领域远超关系型数据库&…

pycharm 占满磁盘

磁盘里没装什么大文件,发现磁盘被占的越来越满,使用工具查看到底是哪个文件如此之大。 发现罪魁祸首是pycharm!!! 根据工具的提示找到对应的路径文件:E:\pycharm\PyCharmCE2022.3\python_packages 发现pa…

五、 计算机网络(考点篇)

1 网络概述和模型 计算机网络是计算机技术与通信技术相结合的产物,它实现了远程通信、远程信息处理和资源共享。计算机网络的功能:数据通信、资源共享、管理集中化、实现分布式处理、负载均衡。 网络性能指标:速率、带宽(频带宽度或传送线路…

java Web学习笔记(三)

文章目录 1. 前置知识2. Vue使用vite构建项目SFC入门使用ref和.value体会响应式数据&#xff08;使用ES6和setup&#xff09; 3. Vue视图渲染技术及其语法模板语法&#xff1a;命令插值表达式渲染双标><中的文本&#xff08;还挺可爱&#xff09;属性渲染命令事件渲染命令…

php安装Imagick扩展 处理pdf为图片

这个方法是使用源码编译安装&#xff0c;适用于php编译安装和包安装。如果有pecl&#xff0c;直接安装就行&#xff0c;我这是因为多个环境怕直接使用pecl工具导致混乱。 由于浏览器显示大量pdf不方便&#xff0c;我这先将pdf转化为图片再显示 如果没有安装php&#xff0c;这是…

智能家居装修怎么布线?智能家居网络与开关插座布置

打造全屋智能家居。计划的智能家居方案以米家系列为主&#xff0c;智能家居联网方案以无线为主。装修前为了装备智能家居做了很多准备工作&#xff0c;本文深圳侨杰智能分享一个智能家居装修和布线方面的心得与实战知识。希望能对大家的装修有所帮助。 ​1.关于网络 如果房子比…

春招冲刺百题计划|堆

Java基础复习 Java数组的声明与初始化Java ArrayListJava HashMapJava String 类Java LinkedListJava Deque继承LinkedListJava SetJava 队列优先队列:第二题用到了 第一题&#xff1a;215. 数组中的第K个最大元素 可以直接使用Arrays.sort()快排&#xff0c;然后return nums…

数据库第六次

视图 salary decimal(10,2) not null default 0 comment ‘工资’, address varchar(200) not null default ‘’ comment ‘通讯地址’, dept_id int comment ‘部门编号’ ); create index idx_name on emp(emp_name); create index idx_birth on emp(birth); create index…

MySQL-日志-优化

目录 介绍一下mysql 的日志 redo log 和binlog 的区别及应用场景 redo log 和 binlog 在恢复数据库有什么区别? redo log 是怎么实现持久化的? redo log除了崩溃恢复还有什么其他作用? &#xff08;顺序写&#xff09; redo log 怎么刷入磁盘的知道吗&#xff1f; 两阶…

2024西安铁一中集训DAY2 ---- 模拟赛(最小生成树 + AC自动机 + 模拟 + rmq)

文章目录 比赛成绩题解A. 江桥的生成树&#xff08;MST&#xff09;B. 江桥的神秘密码&#xff08;AC自动机&#xff0c;ST表&#xff09;C. 江桥的字符距离D. 江桥的防御力测试&#xff08;rmq&#xff0c;乱搞&#xff09; 比赛成绩 估测&#xff1a;60 100 100 0 260 实…

FastAPI 学习之路(四十九)WebSockets(五)修复接口测试中的问题

其实代码没有问题&#xff0c;但是我们忽略了一个问题&#xff0c;就是在正常的开发中&#xff0c;肯定是遇到过这样的情况&#xff0c;我们频繁的有客户端链接&#xff0c;断开连接&#xff0c;需要统一的管理这些链接&#xff0c;那么应该如何管理呢。其实可以声明一个类去管…