传输层协议之UDP

news/2024/9/13 16:42:12/ 标签: udp, 网络, linux

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.ppmy.cn/news/1475880.html

相关文章

一文学会鉴别“套壳”ChatGPT模型

一文学会鉴别“套壳”ChatGPT模型 随着ChatGPT等明星模型的诞生,市场上也开始出现一些“套壳”现象,即部分模型表面标榜原创或先进,实则在核心算法上与知名模型高度相似。作为技术探索者,如何拨开迷雾,识别这些“李鬼…

蓝桥杯14小白月赛题解

直接输出pi/ti,for遍历 #include <iostream> using namespace std; #define int long long int a,b,c ; double t1.00; signed main() {cin>>a;int an0;for(int i1;i<a;i){cin>>b>>c;if(t>c*1.00/b){tc*1.00/b;ani;} }cout<<an<<e…

MYSQL--第八次作业

MYSQL–第八次作业 一、备份与恢复 环境搭建&#xff1a; CREATE DATABASE booksDB; use booksDB;CREATE TABLE books ( bk_id INT NOT NULL PRIMARY KEY, bk_title VARCHAR(50) NOT NULL, copyright YEAR NOT NULL );CREATE TABLE authors ( auth_id INT NOT NULL PRI…

老物件线上3D回忆展拓宽了艺术作品的展示空间和时间-深圳华锐视点

在数字技术的浪潮下&#xff0c;3D线上画展为艺术家们开启了一个全新的展示与销售平台。这一创新形式不仅拓宽了艺术作品的展示空间&#xff0c;还为广大观众带来了前所未有的观赏体验。 3D线上画展制作以其独特的互动性&#xff0c;让艺术不再是单一的视觉享受。在这里&#x…

大数据之路 读书笔记 Day6 离线数据开发之数据开发平台

回顾 Day5 数据同步遇到的问题与解决方案Day4 数据同步 1. 统一计算平台 1.1 MaxCompute概述 MaxCompute&#xff08;原名 ODPS&#xff0c;Open Data Processing Service&#xff09;是阿里云提供的一种快速、完全托管的EB级数据仓库解决方案。它为用户提供了海量数据存储和实…

STM32智能无人机控制系统教程

目录 引言环境准备智能无人机控制系统基础代码实现&#xff1a;实现智能无人机控制系统 4.1 数据采集模块 4.2 数据处理与控制算法 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;无人机管理与优化问题解决方案与优化收尾与总结 1. 引言 智能无人机控…

[终端安全]-6 移动终端之应用程序安全

笔者在终端安全专题前面的文章中介绍了移动终端硬件安全和操作系统安全&#xff0c;本文主要介绍移动终端应用安全。在本文最前面&#xff0c;笔者想先解答一位朋友的疑问&#xff0c;为什么需要费心打造一个完整的面面俱到的安全体系&#xff1f; 1 移动终端安全的重要性 移…

C++——类和对象(上)

文章目录 一、类的定义1.类定义格式2.访问限定符3.类域 二、实例化1.实例化概念2.对象⼤⼩ 三、 this指针 一、类的定义 1.类定义格式 与定义结构体类似 class ST {//成员变量int val;//成员函数void print(){cout << val << endl;}};class为定义类的关键字&…

P2p网络性能测度及监测系统模型

P2p网络性能测度及监测系统模型 网络IP性能参数 IP包传输时延时延变化误差率丢失率虚假率吞吐量可用性连接性测度单向延迟测度单向分组丢失测度往返延迟测度 OSI中的位置-> 网络层 用途 面相业务的网络分布式计算网络游戏IP软件电话流媒体分发多媒体通信 业务质量 通过…

【机器学习】Exam4

实现线性不可分logistic逻辑回归 我们目前所学的都是线性回归&#xff0c;例如 y w 1 x 1 w 2 x 2 b y w_1x_1w_2x_2b yw1​x1​w2​x2​b 用肉眼来看数据集的话不难发现&#xff0c;线性回归没有用了&#xff0c;那么根据课程所学&#xff0c;我们是不是可以增加 x 3 x…

【Linux】Vim 使用教程

Linux - Vim Vim 是一款在 Linux 系统中广泛使用的文本编辑器&#xff0c;它是 Vi 编辑器的升级版。Vim 不仅功能强大&#xff0c;而且可高度定制化&#xff0c;是许多程序员和系统管理员的首选工具。以下是 Vim 在 Linux 系统中的安装、配置和使用过程的详细讲解。 附注&…

Gitea 仓库事件触发Jenkins远程构建

文章目录 引言I Gitea 仓库事件触发Jenkins远程构建1.1 Jenkins配置1.2 Gitea 配置引言 应用场景:测试、生产环境的项目自动构建和部署 手动构建和部署 Gitea 仓库事件触发Jenkins远程构建I Gitea 仓库事件触发Jenkins远程构建 Gitea支持用于仓库事件的Webhooks 1.1 Jenkin…

3-2 多层感知机的从零开始实现

import torch from torch import nn from d2l import torch as d2lbatch_size 256 # 批量大小为256 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size) # load进来训练集和测试集初始化模型参数 回想一下&#xff0c;Fashion-MNIST中的每个图像由 28 28 784…

GraphQL在Postman中:释放API查询的强大潜能

&#x1f680; GraphQL在Postman中&#xff1a;释放API查询的强大潜能 Postman作为API开发和测试的领先工具&#xff0c;对GraphQL的支持为开发者提供了一种新的方式来查询和管理数据。GraphQL是一种查询语言&#xff0c;用于API&#xff0c;允许客户端明确指定他们需要哪些数…

Java数据结构-链表与LinkedList

链表 链表的概念 链表是一种物理存储结构上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序实现的。 通俗来说&#xff0c;相比较于顺序表&#xff08;物理上连续&#xff0c;逻辑上也连续&#xff09;&#xff0c;链表物理上不一定连续。 链表是…

OpenGL笔记十之Shader类的封装

OpenGL笔记十之Shader类的封装 —— 2024-07-10 晚上 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记十之Shader类的封装1.运行2.目录结构3.main.cpp4.application4.1.CMakeLists.txt4.2.Application.h4.3.Application.cpp 5.assets5.1.shaders&#xf…

CentOS7 安装 git 命令

通过yum源install下载的git版本比较低&#xff0c;不推荐此方式安装。 官网下载最新版git源码&#xff1a;Git 1. 解压安装包 tar -xzvf git-2.45.2.tar.gz 2. 安装相关依赖 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils…

【qt】正则表达式来判断是否为邮箱登录

正则表达式是用来匹配字符串的神器. 在Qt中我们需要使用到QRegExp这个类 用exactMatch来进行匹配. [] 使用方括号 [] 来定义字符类&#xff0c;表示匹配方括号内的任意一个字符 A-Za-z0-9是字符的匹配范围. 是用于指定字符或字符类出现的次数,常见的如下 *&#xff08;匹配 0…

07:串口通信二

串口编程 1、与波特率之相关的寄存器2、PCON寄存器3、SCON寄存器4、配置的代码分析5、向PC发送一段字符串6、PC机向单片机发送字符控制LED1灯的亮灭 1、与波特率之相关的寄存器 如图&#xff0c;与串口通信相关的寄存器主要是SCON和PCON寄存器。 2、PCON寄存器 SMOD&#xff1…

【postgresql】锁

PostgreSQL 提供了多种锁模式来控制对表和行的并发访问&#xff0c;以确保数据的一致性和完整性。这些锁模式包括表级锁和行级锁&#xff0c;它们可以由应用程序显式控制&#xff0c;也可以在执行大多数 PostgreSQL 命令时自动获取。 锁类型 PostgreSQL类型的锁包括&#xff…