【Linux网络】:UDP(传输层协议)

目录

一、铺垫知识

1、传输层

2、端口号

 2.1、五元组表示 一个进程通信

2.2、端口号范围划分

2.3、知名端口

2.4、查看端口号

2.5、问题 

3、pidof & netstat 命令 

①netsate 命令

②pidof命令 

二、UDP协议

1、UDP协议格式

2、UDP报文

1.1、UDP数据封装的过程

1.2、UDP数据交付的过程

3、UDP特点

3.1、面向数据报

4、UDP缓冲区

5、UDP传输最大长度

6、基于UDP的应用层协议

一、铺垫知识

1、传输层

 通过HTTP/HTTPS的学习,对应用层有了一定的认识,接下来就是下一层协议:传输层协议。

两台计算机通过TCP/IP协议通讯的大致过程如下:

中间的传输层和网络层是在内核实现的,而应用层是在用户层实现的,这也就注定了在进行学习传输层的时候必然就是要学习在Linux内核中的关于网络的部分,实际上传输层在操作系统的内部是提供了一套对应的系统调用,然后进行正常的数据读取,那对于这部分系统调用也有很多的接口,比如在创建套接字的时候有listen,bind,receive这样的接口,所以下一步要学习的内容就在传输层当中。

2、端口号

在学传输层前,先谈谈端口号,对于端口号的话题在之前已经学习过了,这里只是想说对于端口号的认识,作为一台主机来说,服务器可能会有很多的应用服务,每一个应用服务都要绑定一个明确的端口号,那这个端口号的意义就是能够保证让数据传输给上面的那一个应用程序,因为对于进程的区分就可以借助这个端口号来进行区分,借助ip地址和端口号就可以做到在全网找到唯一的一台主机,而从这个主机上找到唯一的一个进程,这样就能精确的找到对应的网络服务了。

 2.1、五元组表示 一个进程通信

在 TCP/IP 协议中,用 “源IP”,“源端口号”,“目的 IP”,“目的端口号”,“协议号” 这样一个五元组来标识一个通信。 举例:打开浏览器后,添加多个同账户页面访问 CSDN,虽然源 IP 地址是一样的,但是源端口号不同,就表示两个不同的通信。通过这个五元组,服务器能够准确的区分请求是从哪里来的。

所以现在我们可以大致的清楚通信的流程:

  1. 先提取出数据当中的目的 IP 地址目的端口号,确定该数据是发送给当前服务进程的。
  2. 然后提取出数据当中的协议号,为该数据提供对应类型的服务。
  3. 最后提取出数据当中的源 IP 地址源端口号,将其作为响应数据的目的 IP 地址和目的端口号,将响应结果发送给对应的客户端进程。

2.2、端口号范围划分

端口号是一个 16 位的整数,它的取值范围是 0~65535。

  • 0~1023:知名端口号。比如 HTTP,FTP,SSH 等这些广为使用的应用层协议,它们的端口号都是固定的。(类比 120 或 110)
  • 1024~65535:操作系统动态分配的端口号。客户端程序的端口号就是由操作系统从这个范围分配的,允许用户手动绑定。

2.3、知名端口

有些服务器是非常常用的,为了使用方便,人们约定一些常用的服务器,都是用以下这些固定的端口号:

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

2.4、查看端口号

可以通过命令 vim /etc/services 查看文件内容,该文件是记录网络服务名和它们对应使用的端口号及协议。当自己写一个程序使用端口号时,要避开这些知名端口号。

2.5、问题 

一个进程可不可以 bind 多个端口号?

可以。假设绑定了两个端口号 A 和 B,这两个端口号标识的是同一个进程 ,这与端口号用来标识进程的唯一性并不冲突。

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

不行,因为端口号的作用就是标识唯一的一个进程。

如果绑定了多个进程,如何找到对应的进程呢?所以如果绑定一个已经被绑定的端口号就会出现绑定失败的问题。

3、pidof & netstat 命令 

①netsate 命令

netstat 是一个用来查看网络状态的重要工具。

sudo netstat -ntlp  查看TCP相关网络信息

sudo netstat -nulp 查看UDP相关网络信息

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

②pidof命令 

通过进程名来查看服务器进程的 pid。

ps axj | grep UdpServer

pidof UdpServer

二、UDP协议

学习传输层的协议,要从UDP协议入手,其中一个原因是UDP协议还是相对简单一些。

任何协议进行封装后都要进行解包,那如何辨别有效载荷和报头呢?

对于这个问题在自定义协议当中,我们采取的策略是使用了一个\n来进行标记,在前面也有对应的字符串长度来进行解析,而在http协议中采用的方案是用了空行来进行对应的分割工作,那在UDP当中呢?如下:

1、UDP协议格式

  • 16 位源端口号:表示数据从哪里来。
  • 16 位目的端口号:表示数据要到哪里去。
  • 16 位 UDP 长度:表示整个数据报(UDP 首部 + UDP 数据)的最大长度。
  • 16 位 UDP 检验和:如果UDP报文的检验和出错,就会直接将报文丢弃。

UDP的定义十分简单粗暴,就是一个定长报头,规定前面的这些字段就是定长的,规定前8个字节就是报头,剩下的部分就是有效载荷

为什么我们前面在应用层编写代码的时候,每一次写端口号都喜欢用 uint16_t 呢?

其根本原因就是因为传输层协议中的端口号就是 16 位的。

send 数据并不是直接发送到网络里,而是发给了传输层。然后传输层再通过网络协议栈继续发送。那接收端如何将报头和有效载荷进行分离?

UDP 采用的是固定报头,UDP 的报头中只包含四个字段,每个字段的长度都是 16 位,总共 8 字节,所以直接提取前 8 个字节就是报头,其他的就是有效载荷。UDP 具有将报文一个个正确接收的能力,UDP 是面向数据报的。

UDP 如何交付?(有效载荷交给上层的哪一个协议?)

应用层每个进程都绑定有端口号,UDP 就是通过报头当中的目的端口号来找到对应的应用层进程的,把有效载荷交出去。

2、UDP报文

这里的报头其实就是一种结构化数据对象(位段):

struct udp_hdr
{uint16_t src_port;  // 源端口uint16_t dsc_port;  // 目的端口uint16_t udp_len;   // UDP长度uint16_t udp_check; // 校验和
};

这个结构体中的内容其实都与上面的图中所示的报头字段一一对应,而实际上对于UDP的报头理解确实可以理解为是对于UDP的字段填充的过程。 

1.1、UDP数据封装的过程

那么如果要是使用UDP协议向网络中发送Hello World这样的字段,该如何理解这个过程呢?
首先要知道应用层 sendto 数据是发给传输层的。

创建一块内存,计算出有效载荷的起始地址,拷贝有效载荷,强转填写报头部分,最后形成 UDP 报文。

操作系统会提供一个类似于缓冲区的这样的一段区域,那在这个缓冲区中就会构建对应的UDP请求,未来都是会在这个地方通过操作系统向对方发送UDP对应的报文,那这段UDP的报文会在内核中进行流动,它未来是要向下交互到底层硬件进行发送的,这就必然意味着在操作系统的内部会存在很多的UDP的报文

站在接收方的角度来讲,未来它也会受到大量的UDP的报文,所以操作系统必然要对于这么多的UDP报文进行管理,因此在操作系统内部会存在这个叫做sk_buff的结构体

在这个结构体中会有对应的start,end,pos指针,那当未来要构建一个UDP的报文,在内核的层面上就会定义一段缓冲区,之后把前面定义的报头部分拷贝进来,然后再把用户空间的Hello World拷贝进来,然后把对应的start,end,pos这样的指针进行一个描述,这样对于当前UDP的报文就管理起来了,之后在内核中可以使用链表,来把这一个一个的UDP报文进行链接管理起来,这样就能实现对于内核中UDP报文的管理工作

至此,UDP的传输原理其实就是这样,虽然在内核中的实际实现并不是这样,但是基本思想确实如此,未来有机会再对于源码中的UDP部分进行分析详解。

1.2、UDP数据交付的过程

因为是定长报头,直接取出目的端口号,把有效载荷向上交付给指定协议(进程)。

3、UDP特点

UDP 传输的过程类似于寄信。

  • 无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接。
  • 不可靠:没有确认机制,没有重传机制。如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息。
  • 面向数据报:不能够灵活的控制读写数据的次数和数量。要读取就必须读取一个完整的报文。

3.1、面向数据报

举例理解:别人发了三个快递,那么我们就一定要收到三个,不会出现只收到一个,一个半这样的情况。如果只有一个包裹,那我们也不能只拿走一半。结论:发送了一个报文,要么不读,要么 recvfrom 等到读取完一整个报文再返回。

应用层交给 UDP 多长的报文,UDP 原样发送,既不会拆分,也不会合并。

用 UDP 传输 100 个字节的数据:如果发送端调用一次 sendto,发送 100 字节,那么接收端也必须调用对应的一次recvfrom,接收100个字节;而不能循环调用10次recvfrom,每次接收10个字节。

4、UDP缓冲区

严格意义上来说:

  • UDP 没有真正意义上的发送缓冲区。因为它没有可靠机制,不需要把数据暂存起来。它直接调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。
  • UDP 是只有接收缓冲区。这个缓冲区是用来保存用户暂时来不及处理的报文,但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致,如果缓冲区满了,再到达的 UDP 数据就会被丢弃。

UDP 的 socket 既能读,也能写,所以是全双工的。

为什么 UDP 要有缓冲区?

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

5、UDP传输最大长度

UDP 协议首部中有一个 16 位的最大长度,因此一个 UDP 能传输的数据最大长度是 64K(包含 UDP 报头的大小)。

然而 64K 在当今的互联网环境下是一个非常小的数字,如果我们要传输的数据大于 64K,就需要在应用层进行手动分包,多次发送并在接收端进行手动拼装。

6、基于UDP的应用层协议

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

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

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

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

相关文章

Effective C++ 条款19: 设计class犹如设计type

Effective C 条款19:设计class犹如设计type核心思想:设计新的class时,应当像语言设计者设计内置类型一样慎重,考虑对象的创建、销毁、初始化、拷贝、类型转换等所有方面。 ⚠️ 1. 类设计的关键问题域 对象生命周期管理&#xff1…

《汇编语言:基于X86处理器》第11章 MS-Windows编程(3)

本章展示的是如何用32 位Microsoft Windows API进行控制台窗口编程。应用编程接口(API:ApplicationProgramming Interface)是类型、常数和函数的集合体,它提供了一种用计算机代码操作对象的方式。本章将讨论文本I/O、颜色选择、时间与日期、数据文件I/O,…

在 macOS 上通过 Docker 部署DM8 (ARM 架构)

概述 达梦数据库 (DM8) 无法直接在 Apple macOS 操作系统上原生安装,通常需要通过虚拟机(如 Parallels Desktop、VMware Fusion)进行部署。另一种更轻量级且受 macOS 支持的方案是利用 Docker 容器技术来构建开发与测试环境。本文档将详细介…

网络协议之路由是怎么回事?

写在前面 要想去外面的世界看看, 就离不了路由器,而路由器工作的原理就是路由,那么具体是怎么路由的呢?本文就一起来看下这部分内容。 1:路由的配置 配置一条路由无非就是在配置以下三个信息: 1:包要去哪里&#x…

2106. 摘水果,梳理思路

文章目录题目概要java 解法详解题目概要 在一个无限的 x 坐标轴上,有许多水果分布在其中某些位置。给你一个二维整数数组 fruits ,其中 fruits[i] [positioni, amounti] 表示共有 amounti 个水果放置在 positioni 上。fruits 已经按 positioni 升序排列…

深入理解消息队列(MQ)核心原理与设计精髓

引言:从一个“不堪重负”的订单系统说起想象一个简化的电商下单流程:用户点击“下单”后,系统需要:在订单数据库中创建一条记录。调用库存服务,扣减商品库存。调用营销服务,给用户发放积分和优惠券。调用通…

前端手撕题总结篇(算法篇——来自Leetcode牛客)

链表指定区域反转 找到区间(头和为 for循环当**时)->反转链表(返回反转过后的头和尾)->连接 function reverseBetween( head , m , n ) {//preEnd&cur&nextStart cur.next断开if(mn)return head;const vHeadNode…

从Excel到工时管理系统:企业如何选择更高效的工时记录工具?

还在为手工统计员工工时而头疼吗?月末堆积如山的Excel表格、反复核对的数据、层出不穷的差错,这些问题正在拖慢企业的发展步伐。8Manage工时管理系统发现,传统手工记录不仅耗费大量人力,更让宝贵的工时数据难以转化为有效的管理决…

Java设计模式之《命令模式》

目录 1、介绍 1.1、命令模式定义 1.2、对比 1.3、典型应用场景 2、命令模式的结构 2.1、组成部分: 2.2、整体流程 3、实现 3.1、没有命令模式 3.2、命令模式写法 4、命令模式的优缺点 前言 java设计模式分类: 1、介绍 1.1、命令模式定义 命…

【动态规划算法】路径问题

什么是动态规划算法动态规划(Dynamic Programming,简称 DP)是一种通过分解复杂问题为重叠子问题,并存储子问题的解以避免重复计算,从而高效求解具有特定性质(重叠子问题、最优子结构)问题的算法…

Java基本技术讲解

一、基础语法三要素 暂时无法在飞书文档外展示此内容 🔑 黄金法则​:每个变量都要声明类型!二、程序逻辑控制(游戏行为核心) 条件判断:if-else - “岔路口选择” // 捡到金币逻辑 if (isTouching(Coin.clas…

【网络基础2】路由器的 “两扇门”:二层接口和三层接口到底有啥不一样?

目录 前言:路由器不是只有 “插网线的口” 一、先搞懂一个基础:路由器是 “网络交通枢纽” 二、二层接口:“小区内部的单元门”,只认 “住户身份证” 1. 啥是二层接口? 2. 用 “小区内部串门” 理解二层接口 步骤 1:手机打包数据,写上 “收件人身份证” 步骤 2:二…

MLIR TableGen

简介 TableGen 是一种领域特定语言(DSL),TableGen 的设计目标是允许编写灵活的描述,并将记录的通用特性提取出来,从而减少重复代码并提高代码的可维护性。 TableGen的工作流程: 前端解析: Ta…

2、docker容器命令 | 信息查看

1、命令总览命令作用docker ps查看运行中的容器(-a查看所有容器)docker logs [CONTAINER]查看容器日志(-f实时追踪日志)docker inspect [CONTAINER]查看容器详细信息(JSON格式)docker stats [CONTAINER]实时…

【MySQL】MySQL中锁有哪些?

一、按照粒度分类: 粒度越小,并发度越高,锁开销越大。 1.全局锁: 作用: 锁定整个MySQL实例(所有数据库)。适用场景: 全库逻辑部分。(确保备份期间数据的一致性。)实现方式: 通过 FLUSH TABLES W…

语义分割--deeplabV3+

根据论文网络结构图讲一下:网络分为两部分:encoder和decoder部分。 Encoder:DCNN就是主干网络,例如resnet,Xception,MobileNet这些(主干网络也要使用空洞卷积),对dcnn的结…

Azure DevOps 中的代理

必知词汇 深入研究 Azure DevOps 中的代理之前需要掌握的基本概念: 代理:Azure DevOps 中的代理是一个软件组件,负责执行流水线中的任务和作业。这可能包括数据中心内的物理服务器、本地或云端托管的虚拟机,甚至是容器化环境。这些代理可以在各种操作系统和环境中运行,例如…

AUTOSAR进阶图解==>AUTOSAR_SRS_ADCDriver

AUTOSAR ADC驱动详解 基于AUTOSAR标准的ADC驱动模块需求规范分析目录 ADC驱动模块概述 关键概念定义 ADC驱动架构 ADC驱动在AUTOSAR分层架构中的位置ADC驱动的主要职责 ADC驱动配置结构 通用配置(AdcGeneral)硬件单元配置(AdcHwUnit)通道配置(AdcChannel)通道组配置(AdcChanne…

宝马集团与SAP联合打造生产物流数字化新标杆

在德国雷根斯堡的宝马工厂,每57秒就有一辆新车下线。这座工厂不仅是汽车制造的基地,更是宝马集团向SAP S/4HANA云平台转型的先锋项目。通过“RISE with SAP”计划,宝马将该工厂的运营系统全面迁移至SAP S/4HANA Cloud Private Edition&#x…

Go 语言实战:构建一个高性能的 MySQL + Redis 应用

引言:为什么是 Go MySQL Redis?在现代后端技术栈中,Go MySQL Redis 的组合堪称“黄金搭档”,被广泛应用于各种高并发业务场景。Go 语言:以其卓越的并发性能、简洁的语法和高效的执行效率,成为构建高性能…