【网络编程】十、详解 UDP 协议

文章目录

  • Ⅰ. 传输层概述
    • 1、进程之间的通信
    • 2、再谈端口号
      • 端口号的引出
      • 五元组标识一个通信
      • 端口号范围划分
      • 常见的知名端口号
      • 查看知名端口号
      • 协议号 VS 端口号
    • 3、两个问题
      • 一个端口号是否可以被多个进程绑定?
      • 一个进程是否可以绑定多个端口号?
    • 4、部分常见指令
      • pidof(用于查看进程id)
      • netstat(查看网络状态)
  • Ⅱ. UDP协议
    • 1、UDP协议所处位置
    • 2、UDP协议格式
      • 如何理解首部?
      • UDP协议如何将首部与有效载荷进行分离?
      • UDP协议如何决定将有效载荷交付给上层的哪一个协议?
    • 3、UDP的主要特点
    • 4、面向数据报
    • 5、UDP协议的缓冲区
      • 为什么UDP要有接收缓冲区?
    • 6、基于UDP的应用层协议

在这里插入图片描述

Ⅰ. 传输层概述

1、进程之间的通信

​ 在学习 HTTP 等应用层协议时,为了便于理解,可以简单的认为 HTTP 协议是将请求和响应直接发送到了网络当中。但实际应用层需要先将数据交给传输层,再由传输层对数据做进一步处理后再将数据继续向下进行交付,该过程贯穿整个网络协议栈,最终才能将数据发送到网络当中。
在这里插入图片描述

​ 传输层负责可靠性传输,确保数据能够可靠地传送到目标地址。从通信和信息处理的角度看,运输层为它上面的应用层提供通信服务
在这里插入图片描述

​ 但是我们要明确的是,真正进行通信的实体,其实是主机中的应用进程,也就是进程之间的通信!而为了达到传输层向上服务应用层的时候,可以找到对应的进程,就有了两个重要的功能:复用分用!如下图所示:
在这里插入图片描述

​ 此外,传输层还要对收到的报文进行差错检测,只不过 传输层只检验首部是否出现差错,而不检查有效载荷部分!

2、再谈端口号

端口号的引出

​ 应用层所有的应用进程都可以通过运输层再传送到网络层,这叫做复用;而运输层从网络层收到发送给各应用进程的数据后,必须分别交付指明的各应用进程,这就是分用。

​ 所以很明显,给应用层的每个应用进程赋予一个非常明确唯一的标志是至关重要的

​ 我们知道,一台计算机中的进程有着唯一标识的进程标识符,但因为这个进程标识符和操作系统是强相关的,如果我们将其作为复用和分用的标识的话,那么会有一个问题,就是一个进程的标识符由操作系统管理,所以进程的销毁和创建都会导致进程标识符的变化,但是我们又是希望在网络中传输的时候,对方的唯一标志可以是尽量保持不变的(因为一旦变化,请求连接的标识也需要改变),所以我们 不能用进程标识符作为复用和分用的唯一标志

​ 所以此时就有人使用了端口号这种方案来作为唯一标识!

端口号(Port)标识一个主机上进行网络通信的不同的应用程序。当主机从网络中获取到数据后,需要自底向上进行数据的交付,而这个数据最终应该交给上层的哪个应用处理程序,就是由该数据当中的目的端口号来决定的。

​ 从网络中获取的数据在进行向上交付时,在传输层就会提取出该数据对应的目的端口号,进而确定该数据应该交付给当前主机上的哪一个服务进程。
在这里插入图片描述

​ 因此端口号是属于传输层的概念的,在传输层协议的报头当中就会包含与端口相关的字段。

​ 请注意,端口号只具有本地意义,在互联网不同的计算机中,相同的端口号是没有关联的!

五元组标识一个通信

​ 在 TCP/IP 协议中,用 “源IP地址”、“源端口号”、“目的IP地址”、“目的端口号”、“协议号” 这样一个五元组来标识一个通信。

​ 比如有多台客户端主机同时访问服务器,这些客户端主机上可能有一个客户端进程,也可能有多个客户端进程,它们都在访问同一台服务器。
在这里插入图片描述

而这台服务器就是通过 “源IP地址”、“源端口号”、“目的IP地址”、“目的端口号”、“协议号” 来识别一个通信的。

  • 先提取出数据当中的目的 IP 地址和目的端口号,确定该数据是发送给当前服务进程的。
  • 然后提取出数据当中的协议号,为该数据提供对应类型的服务。
  • 最后提取出数据当中的源 IP 地址和源端口号,将其作为响应数据的目的IP地址和目的端口号,将响应结果发送给对应的客户端进程。
    在这里插入图片描述

​ 通过 netstat 命令可以查看到这样的五元组信息。
在这里插入图片描述

​ 其中的 Local Address 表示的就是源IP地址和源端口号,Foreign Address 表示的就是目的IP地址和目的端口号,而 Proto 表示的就是协议类型。

端口号范围划分

端口号的长度是 16,因此端口号的范围是 0 ~ 65535

  • 0 ~ 1023知名端口号。比如 HTTPFTPSSH 等这些广为使用的应用层协议,它们的端口号都是固定的。
  • 1024 ~ 65535操作系统动态分配的端口号。客户端程序的端口号就是由操作系统从这个范围分配的。

常见的知名端口号

有些服务器是非常常用的,这些服务器的端口号一般都是固定的:

  • ssh 服务器,使用 22 端口
  • ftp 服务器,使用 21 端口
  • telnet 服务器,使用 23 端口
  • dns 服务器,使用 53 端口
  • http 服务器,使用 80 端口
  • https 服务器,使用 443 端口

查看知名端口号

​ 我们可以查看 /etc/services 文件,该文件是记录网络服务名和它们对应使用的端口号及协议。
在这里插入图片描述

说明一下:文件中的每一行对应一种服务,它由 4 个字段组成,每个字段之间用 TAB 或空格分隔,分别表示“服务名称”、“使用端口”、“协议名称”以及“别名”。

协议号 VS 端口号

  • 协议号是存在于 IP 报头当中的,其长度是 8 位。协议号指明了数据报所携带的数据是使用的何种协议,以便让目的主机的 IP 层知道应该将该数据交付给传输层的哪个协议进行处理。
  • 端口号是存在于 UDPTCP 报头当中的,其长度是 16 位。端口号的作用是唯一标识一台主机上的某个进程。
  • 协议号是作用于传输层和网络层之间的,而端口号是作用于应用层于传输层之间的。

3、两个问题

一个端口号是否可以被多个进程绑定?

一个端口号绝对不能被多个进程绑定,因为端口号的作用就是唯一标识一个进程,如果绑定一个已经被绑定的端口号,就会出现绑定失败的问题。

一个进程是否可以绑定多个端口号?

一个进程是可以绑定多个端口号的,这与“端口号必须唯一标识一个进程”是不冲突的,只不过现在这多个端口唯一标识的是同一个进程罢了。

​ 我们限制的是从端口号到进程的唯一性,而没有要求从进程到端口号也必须满足唯一性,因此一个进程是可以绑定多个端口号的。

4、部分常见指令

pidof(用于查看进程id)

pidof httpServer | xargs kill -9 // xargs用于将管道前面获取的参数追加到该指令后面

netstat(查看网络状态)

n  拒绝显示别名,能显示数字的全部转化成数字
l  仅列出有在 Listen (监听) 的服务状态
p  显示建立相关链接的程序名
t(tcp)  仅显示tcp相关选项
u(udp)  仅显示udp相关选项
a(all)  显示所有选项,默认不显示LISTEN相关

Ⅱ. UDP协议

1、UDP协议所处位置

​ 网络套接字编程时用到的各种接口,是位于应用层和传输层之间的一层系统调用接口,这些接口是系统提供的,我们可以通过这些接口搭建上层应用,比如 HTTP。我们经常说 HTTP 是基于 TCP 的,实际就是因为 HTTPTCP 套接字编程上搭建的。

​ 而 socket 接口往下的传输层实际就是由操作系统管理的,因此 UDP 是属于内核当中的,是操作系统本身协议栈自带的,其代码不是由上层用户编写的,UDP 的所有功能都是由操作系统完成,因此网络也是操作系统的一部分。

2、UDP协议格式

​ 其格式如下:
在这里插入图片描述

  • 16 位源端口号:表示数据从哪里来。
  • 16 位目的端口号:表示数据要到哪里去。
  • 16 位整个报文长度:表示整个数据报(UDP 首部 + UDP 数据)的长度。
    • 这也就说明 UDP 最大可传输的长度为 2^1664KB(包含首部字段),如果需要 传输大于 64KB 的数据,就需要应用层多次分包,并在接收端手动拼装
  • 16 位检验和:如果 UDP 报文的检验和出错,就会直接将报文丢弃。

​ 之所以我们在应用层看到的端口号大部分都是 16 位的,比如使用 uint16_t 类型,其根本原因就是因为传输层协议当中的端口号就是 16 位的。

如何理解首部?

​ 操作系统是 C 语言写的,而 UDP 协议又是属于内核协议栈的,因此 UDP 协议也一定是用 C 语言编写的,所以 UDP 首部本质上是一个结构体对象或者包含位段的结构体,如下所示:

struct udphdr {uint16_t uh_sport;  /* 源端口号 */uint16_t uh_dport;  /* 目的端口号 */uint16_t uh_ulen;   /* UDP数据报长度(包括头部+数据) */uint16_t uh_sum;    /* 数据校验和 */
};

UDP数据封装:

  • 当应用层将数据交给传输层后,在传输层就会创建一个 UDP 报头类型的变量,然后填充报头当中的各个字段,此时就得到了一个 UDP 报头。
  • 此时操作系统再在内核当中开辟一块空间,将 UDP 报头和有效载荷拷贝到一起,此时就形成了 UDP 报文。

UDP数据分用:

  • 当传输层从下层获取到一个报文后,就会读取该报文的前 8 个字节,提取出对应的目的端口号。
  • 通过目的端口号找到对应的上层应用层进程,然后将剩下的有效载荷向上交付给该应用层进程。

UDP协议如何将首部与有效载荷进行分离?

UDP的报头当中只包含四个字段,每个字段的长度都是 16 位,总共 8 字节。因此 UDP 采用的实际上是一种定长报头,UDP 在读取报文时读取完前 8 个字节后剩下的就都是有效载荷了。

​ 而我们只需要提取报头中的 数据报长度 字段,减去 8 个字节,最后的大小就是有效载荷的长度,是可以直接读取上来的!

UDP协议如何决定将有效载荷交付给上层的哪一个协议?

UDP 上层也有很多应用层协议,因此 UDP 必须想办法将有效载荷交给对应的上层协议,也就是交给应用层对应的进程。

​ 应用层的每一个网络进程都会绑定一个端口号,服务端进程必须显示绑定一个端口号,客户端进程则是由系统动态绑定的一个端口号。UDP 就是通过报头当中的目的端口号来找到对应的应用层进程的。

​ 说明一下: 内核中用哈希的方式维护了端口号与进程 ID 之间的映射关系,因此传输层可以通过端口号得到对应的进程 ID,进而找到对应的应用层进程

3、UDP的主要特点

  1. 无连接。发送数据之前不需要建立连接。
  2. 使用尽最大努力交付。即 不保证可靠交付
  3. 面向报文UDP 一次传送和交付一个完整的报文。
  4. 没有拥塞控制。网络出现的拥塞不会使源主机的发送速率降低。很适合多媒体通信的要求。
  5. 支持一对一、一对多、多对一、多对多等交互通信。
  6. 首部开销小,只有 8 个字节。

​ 总结一点,就是【简单方便,但不可靠】。
在这里插入图片描述

​ 此外,应用程序必须选择合适大小的报文。若报文太长,IP 层在传送时可能要进行分片,降低 IP 层的效率。若报文太短,会使 IP 数据报的首部的相对长度太大,降低 IP 层的效率。

4、面向数据报

​ 应用层交给 UDP 多长的报文,UDP 就原样发送,既不会拆分,也不会合并,这就叫做面向数据报。

​ 比如用 UDP 传输 100 个字节的数据:

​ 如果发送端调用一次 sendto,发送 100 字节,那么接收端也必须调用对应的一次 recvfrom,接收 100 个字节,而不能循环调用 10recvfrom 去每次接收 10 个字节。

5、UDP协议的缓冲区

UDP 协议不需要考虑多个报文之间的粘连问题,因为 UDP 没有真正意义上的发送缓冲区。调用 sendto 函数会直接交给内核(应用层发一个,传输层送走一个),由内核将数据传给网络层协议进行后续的传输动作。

​ 但是 UDP 具有接收缓冲区。但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致。如果缓冲区满了,再到达的 UDP 数据就会直接被丢弃,所以 UDP 协议是一种不可靠、全双工的协议。
在这里插入图片描述

为什么UDP要有接收缓冲区?

​ 如果 UDP 没有接收缓冲区,那么就要求上层及时将 UDP 获取到的报文读取上去,如果一个报文在 UDP 没有被读取,那么此时 UDP 从底层获取上来的报文数据就会被迫丢弃。

​ 一个报文从一台主机传输到另一台主机,在传输过程中会消耗主机资源和网络资源。如果 UDP 收到一个报文后仅仅因为上次收到的报文没有被上层读取,而被迫丢弃一个可能并没有错误的报文,这就是在 浪费主机资源和网络资源

​ 因此 UDP 本身是会维护一个接收缓冲区的,当有新的 UDP 报文到来时就会把这个报文放到接收缓冲区当中,此时上层在读数据的时就直接从这个接收缓冲区当中进行读取就行了,而如果 UDP 接收缓冲区当中没有数据那上层在读取时就会被阻塞。因此 UDP 的接收缓冲区的作用就是,将接收到的报文暂时的保存起来,供上层读取。

6、基于UDP的应用层协议

  • NFS:网络文件系统
  • TFTP:简单文件传输协议
  • DHCP:动态主机配置协议
  • BOOTP:启动协议(用于无盘设备启动)
  • DNS:域名解析协议

当然,也包括自己写 UDP 程序时自定义的应用层协议。

在这里插入图片描述

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

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

相关文章

实现RTSP低延迟播放器,挑战与解决方案

随着低延迟直播需求的快速增长,RTSP(Real-Time Streaming Protocol)播放器逐渐成为实时视频流传输中的核心技术之一。与WebRTC(Web Real-Time Communication)相比,RTSP在实时性和网络延迟方面面临诸多挑战&…

【springcloud学习(dalston.sr1)】Eureka单个服务端的搭建(含源代码)(三)

该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) springcloud学习(dalston.sr1)系统文章汇总如下: 【springcloud学习(dalston…

GPU与NPU异构计算任务划分算法研究:基于强化学习的Transformer负载均衡实践

点击 “AladdinEdu,同学们用得起的【H卡】算力平台”,H卡级别算力,按量计费,灵活弹性,顶级配置,学生专属优惠。 引言 在边缘计算与AI推理场景中,GPU-NPU异构计算架构已成为突破算力瓶颈的关键技…

探索C语言中的二叉树:原理、实现与应用

一、引言 二叉树作为一种重要的数据结构,在计算机科学领域有着广泛的应用,无论是在操作系统的文件系统管理,还是在数据库的索引构建中,都能看到它的身影。在C语言中,我们可以利用指针灵活地构建和操作二叉树。接下来&…

使用libUSB-win32的简单读写例程参考

USB上位机程序的编写,函数的调用过程. 调用 void usb_init(void); 进行初始化 调用usb_find_busses、usb_find_devices和usb_get_busses这三个函数,获得已找到的USB总线序列;然后通过链表遍历所有的USB设备,根据已知的要打开USB设…

vue注册用户使用v-model实现数据双向绑定

定义数据模型 Login.vue //定义数据模型 const registerData ref({username: ,password: ,confirmPassword: })使用 v-model 实现数据模型的key与注册表单中的元素之间的双向绑定 <!-- 注册表单 --><el-form ref"form" size"large" autocompl…

【Arthas实战】常见使用场景与命令分享

简介: Arthas是一款Java诊断工具&#xff0c;适用于多种场景&#xff0c;如接口响应变慢、CPU占用过高、热更新需求等。其核心命令包括实时监控面板&#xff08;dashboard&#xff09;、线程状态查看&#xff08;thread&#xff09;、方法调用链路追踪&#xff08;trace&#x…

Jenkins 最佳实践

1. 在Jenkins中避免调度过载 过载Jenkins以同时运行多个作业可能导致资源竞争、构建速度变慢和系统性能问题。分配作业启动时间可以防止瓶颈&#xff0c;并确保更顺畅的执行。如何实现&#xff1f; 在Cron表达式中使用H&#xff1a;引入抖动&#xff08;jitter&#xff09;&a…

pytest框架 - 第二集 allure报告

一、断言assert 二、Pytest 结合 allure-pytest 插件生成美观的 Allure 报告 (1) 安装 allure 环境 安装 allure-pytest 插件&#xff1a;pip install allure-pytest在 github 下载 allure 报告文件 地址&#xff1a;Releases allure-framework/allure2 GitHub下载&#x…

人工智能时代:解锁职业新身份,从“认证师”到“工程师”的进阶之路

在人工智能技术浪潮席卷全球的今天,技术的飞速迭代正在重塑职业版图。从算法优化到伦理决策,从系统测试到应用开发,AI技术不再只是程序员的专属领域,而是成为各行各业从业者必须掌握的“生存技能”。当企业争相布局AI赛道,个人如何在这场变革中抢占先机?答案或许藏在两个…

【带文档】网上点餐系统 springboot + vue 全栈项目实战(源码+数据库+万字说明文档)

&#x1f4cc; 一、项目概括 本系统共包含三个角色&#xff1a; 管理员&#xff1a;系统运营管理者 用户&#xff1a;点餐消费用户 美食店&#xff1a;上传菜品与处理订单的店铺账号 通过对这三类角色的权限与业务分工设计&#xff0c;系统实现了点餐流程的全链路数字化&a…

window nvidia-smi命令 Failed to initialize NVML: Unknown Error

如果驱动目录下的可以执行&#xff0c;那可能版本原因 "C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi"复制"C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe"替换 C:\Windows\System32\nvidia-smi.exe 或者 把C:\Windows\System3…

接触感知 钳位电路分析

以下是NG板接触感知电路的原理图。两极分别为P3和P4S&#xff0c;电压值P4S < P3。 电路结构分两部分&#xff0c;第一部分对输入电压进行分压钳位。后级电路使用LM113比较器芯片进行电压比较&#xff0c;输出ST接触感知信号。 钳位电路输出特性分析 输出电压变化趋势&a…

70、微服务保姆教程(十三)Docker容器详细讲义

一、关于Docker 1.1为什么要用docker? 随着开发的项目越来越复杂,软件越来越多,服务器越来越多,我们在开发和部署的时候会遇到很多问题,比如: 1.不同的应用程序可能会有不同的应用环境,比如Java开发的网站和php开发的网站依赖的软件就不一样,如果把他们依赖的软件都…

Python 中的 typing.ClassVar 详解

一、ClassVar 的定义和基本用途 ClassVar 是 typing 模块中提供的一种特殊类型&#xff0c;用于在类型注解中标记类变量&#xff08;静态变量&#xff09;。根据官方文档&#xff0c;使用 ClassVar[…] 注释的属性表示该属性只在类层面使用&#xff0c;不应在实例上赋值 例如&…

架构与UML4+1视图

简单对比分析 架构41视图 架构41视图是由Philippe Kruchten提出的&#xff0c;用于描述软件系统的架构。它包括以下五个视图&#xff1a; 逻辑视图&#xff1a;描述系统的功能需求&#xff0c;展示系统的静态结构&#xff0c;通常使用类图、对象图等。开发视图&#xff1a;…

Redis 八股

目录 数据类型 字符串&#xff1a; List&#xff1a; HASH&#xff1a; Set&#xff1a; Zset&#xff1a; BitMap&#xff1a;&#xff08;这个及以下是后来新增的数据结构&#xff09; HyperLogLog&#xff1a; GEO&#xff1a; Stream&#xff1a; 主要数据结构 …

基于协同过滤的文学推荐系统设计【源码+文档+部署】

基于协同过滤的文学推荐系统设计 摘要 随着信息技术的飞速发展和文学阅读需求的日益多样化&#xff0c;构建一个高效、精准的文学推荐系统变得尤为重要。本文采用Spring Boot框架&#xff0c;结合协同过滤算法&#xff0c;设计并实现了一个基于用户借阅行为和社交论坛互动的文学…

鸿蒙电脑:五年铸剑开新篇,国产操作系统新引擎

出品 | 何玺 排版 | 叶媛 前不久&#xff0c;玺哥发布的《鸿蒙电脑&#xff0c;刺向垄断的利刃&#xff0c;将重塑全球PC市场格局》发布后&#xff0c;获得了读者朋友的积极反馈&#xff0c;不少都期望鸿蒙电脑早日发布。 如今&#xff0c;它真来了&#xff01; 5月8日&…

EWOMAIL

1、错误 Problem: problem with installed package selinux-policy-targeted-3.14.3-41.el8.noarch package fail2ban-server-1.0.2-3.el8.noarch requires (fail2ban-selinux if selinux-policy-targeted), but none of the providers can be installed - package fail2ban-…