【计算机网络】UDP 协议详解及其网络编程应用

文章目录

  • 一、引言
  • 二、UDP
    • 1、UDP的协议格式
    • 2、UDP 报文的解包和分用
    • 3、UDP面向数据报的特点
  • 三、UDP输入输出
  • 四、UDP网络编程

一、引言

UDP(User Datagram Protocol用户数据报协议)是一种网络通信协议,它属于传输层的协议。是一个简单的、面向无连接的协议。UDP用于将数据从一个应用程序发送到另一个应用程序,并在此过程中不提供可靠的数据传输保障。UDP 支持一对一、一对多、多对多的交互通信。

UDP是不具有可靠性的协议。细微的处理它会交给上层的应用去完成。在使用UDP的情况下,虽然可以确保发送消息的大小(例如,发送端应用程序发送一个100字节的消息,那么接收端应用程序也会以100字节为长度接收数据。UDP中,消息长度的数据也会发送到接收端,因此在发送的消息中不需要设置一个表示消息长度或间隔的字段信息。然而,UDP不具备可靠传输。所以,发送端发出去的消息在网络传输途中一旦丢失,接收端将收不到这个消息。) ,却不能保证消息一定会到达。因此,应用有时会根据自己的需要进行重发处理。

UDP不提供复杂的控制机制,利用 IP 提供面向「无连接」的通信服务。

就是说UDP是依赖于底层的IP协议来进行数据传输。IP提供了基本的无连接数据传输服务,UDP在此基础上构建,只是增加了端口号等基本的传输控制功能,但不提供额外的可靠性或连接管理。

由于UDP面向无连接,它可以随时发送数据。再加上UDP本身的处理既简单又高效,因此经常用于以下几个方面:

  • 包总量较少的通信(DNS、SNMP等)
  • 视频、音频等多媒体通信(即时通信)
  • 广播通信(广播、多播)
  • 限定于LAN等特定网络中的应用通信

二、UDP

系统调用接口:网络套接字编程接口位于应用层和传输层之间,是操作系统提供的系统调用接口。它允许应用程序通过一组标准的接口进行网络通信,比如 socket()bind()sendto()recvfrom() 等函数。

内核中的UDP:UDP是由操作系统内核实现的,它属于操作系统协议栈的一部分。UDP的所有功能(如数据报的发送和接收)都是由操作系统负责的,而不是由用户应用程序编写的。

协议栈:操作系统内核提供了完整的网络协议栈,其中包括各种网络协议(如IP、TCP、UDP等)。操作系统通过这些协议栈管理网络通信的底层细节,确保网络数据能够在系统和网络之间正确传输。

网络作为操作系统的一部分:网络功能是操作系统的一部分,因为网络协议的实现和管理都在操作系统内核中完成。操作系统通过提供网络套接字接口,让应用程序可以利用这些内核级别的网络功能进行通信。

网络套接字编程接口提供了一个在应用层与操作系统之间的桥梁,使得应用程序能够使用底层的网络协议(如TCP和UDP)进行通信。HTTP等高层协议利用这些底层协议的特性来实现其功能,而UDP作为内核中的协议,由操作系统负责其实现和管理。这种分层设计使得网络编程变得更加灵活和高效。

1、UDP的协议格式

在这里插入图片描述

UDP数据段的长度为16位,也就是说UDP能传输的最大长度是64K(包括UDP首部字段)。

若传输的数据超过64K,就需要在应用层手动分包,多次发送,并在接收端手动拼装。

校验和(Checksum):用于检测数据在传输过程中是否被篡改或损坏。它是 UDP 首部和数据部分的 16 位字的反码和。这个字段在某些实现中可能是可选的(可以为 0),但在 IPv6 中是强制的。

UDP报头在内核中的实现:

在这里插入图片描述

这个结构体UDPhdr用于表示UDP(用户数据报协议)报头,它通常用于网络编程中。下面是这个结构体中各个字段的含义:

  • source:源端口号,占16位,表示发送方的端口号。
  • dest:目的端口号,占16位,表示接收方的端口号。
  • len:UDP长度,占16位,包括UDP头部和UDP数据的总长度。
  • check:校验和,占16位,用于检测UDP数据在传输过程中是否出现错误。

这个结构体通常用于原始套接字编程,或者在网络协议的实现中。

2、UDP 报文的解包和分用

1. 报文解包

当UDP报文从网络层传递到传输层时,解包过程会解析UDP首部并提取相应的信息:

  1. 接收数据报:网络层将接收到的IP数据报传递给传输层。
  2. 解析UDP首部:传输层解析UDP数据报的前8个字节,从而获取源端口、目的端口、报文长度和校验和。
  3. 校验和验证:通过计算校验和验证数据报的完整性。如果校验和不匹配,数据报会被丢弃。
  4. 提取数据部分:从UDP数据报中提取实际的数据部分,将其交给上层应用。

2. 分用

分用是指将接收到的数据报根据目的端口号分配给不同的应用程序。具体步骤如下:

  1. 检查目的端口:解析出的目的端口号用于确定数据报应该交给哪个应用程序。
  2. 查找对应的进程:操作系统维护一个端口号到进程的映射表,通过目的端口号查找到相应的进程。
  3. 传递数据:将数据报的内容传递给相应的应用程序。

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

3、UDP面向数据报的特点

UDP传输过程类似于寄信。

  1. 无连接性

    UDP是无连接的,意味着发送方和接收方之间不需要建立或维护连接。在UDP中,每个数据报文(数据报)都是独立的,不依赖于前后的数据报。这种无连接特性使UDP特别适合需要快速传输的应用程序,如实时视频流、在线游戏等。

  2. 数据报独立性与无序性

在UDP中,每个数据报都是一个独立的单元。数据报之间没有顺序关系,即使发送顺序被打乱或丢失,也不会影响其他数据报的传输。应用程序必须自行处理数据报的顺序、丢失和重复等问题。而且不保证数据报按发送顺序到达接收端。每个数据报独立传输,接收端收到的数据报可能是乱序的。应用程序需要根据需求自行处理数据的顺序。

  1. 不可靠

    没有确定机制,没有重传机制;若因为网络故障该段无法发送到对方,UDP协议层也不会给应用层返回任何错误信息。UDP没有提供重传机制。如果数据报在传输过程中丢失或损坏,UDP不会自动重传数据。应用程序必须自行处理这些问题,这使得UDP在需要高实时性但对数据可靠性要求不高的场景中非常有效。

如何理解UDP是面向数据报的

UDP(用户数据报协议)是一种无连接、面向数据报的传输层协议。它的设计使其高效且适用于需要快速传输但不需要可靠性保证的应用。

由于UDP提供的是无连接的服务,因此UDP客户与服务之间不存在任何的长期关系。举例来说,一个UDP客户可以创建一个套接字并发送数据报给一个特定的服务器,然后立即用同一个套接字发送另一个数据报给另一个服务器。同样的,一个UDP服务器可以用同一个UDP套接字从若干个不同的客户接收数据报,每个客户一个数据报。

UDP面向数据报的实现:

  1. 数据报传输:在UDP中,每个数据报从发送端到接收端是独立传输的。发送端将数据封装成UDP数据报,通过网络层(IP层)发送到接收端。接收端接收数据报后,提取出UDP首部信息和数据部分,然后将数据交给相应的应用程序处理。

  2. 报文解包:在接收端,UDP首部被解析以获取源端口、目的端口、数据长度和校验和等信息。然后,数据部分被提取出来,根据目的端口号将数据传递给相应的应用程序。

  3. 分用:接收端使用目的端口号来确定哪个应用程序应该接收数据报。这种方式被称为分用。操作系统会维护一个端口号到应用程序的映射表,通过查找表将数据报传递给正确的应用程序。

UDP被称为面向数据报的协议,原因如下:

  • 独立的数据报:每个UDP数据报独立存在,彼此之间没有联系。这种设计意味着数据报可以独立处理和传输,无需依赖其他数据报的状态。
  • 无连接和无状态:UDP不维护连接状态,也不跟踪数据报的传输状态。这使得每个数据报的传输过程独立,不需要为连接的建立、维护或终止花费额外的开销。
  • 简单的首部:UDP首部非常简洁,仅包含必要的信息,使得数据报的处理和解析速度非常快。
  • 不保证可靠性:UDP不保证数据报的可靠传输、不丢失、按序到达。这意味着每个数据报的处理是独立的,不依赖于前后数据报的传输状态。

这些特性使UDP非常适合需要低延迟和高效传输的应用,如视频会议、实时游戏和语音通信等。


三、UDP输入输出

下图展示了一个应用进程写数据到UDP套接字中发生的步骤。

在这里插入图片描述

这一端的UDP简单地给来自用户的数据报安上它的8字节首部以构成UDP数据报,然后传递给IP层。

其中虚线框表示了套接字发送缓冲区,因为它实际并不存在。任何UDP套接字都有份发送缓冲区的大小,不过它仅仅是可写到该套接字的UDP数据报大小的上限。如果一个应用进程写一个大于套接字发送缓冲区大小的数据报,内核将返回进程一个EMSGSIZE错误。UDP是不可靠的,它不必保存应用进程数据的一个副本,因此不必像TCP一样有一个真正的发送缓冲区。

也就是说UDP没有真正意义上的发送缓冲区。调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。

UDP 的发送缓冲区在数据发送成功后,数据会立即从缓冲区中移除,不像 TCP 需要等待接收方的确认。

发送缓冲区(Send Buffer)是一个内核空间中的缓冲区,专门用于临时存储应用程序准备发送的数据。它的作用是在网络协议栈中不同层次之间传递数据时,确保数据能够有序且可靠地传输。

应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中。当数据通过协议栈传递并成功发送后,数据链路层完成了数据的传输任务,此时该数据的副本在发送缓冲区中的存在已经没有意义。因此,内核会将发送缓冲区中的数据副本丢弃,以便释放内存资源给后续需要发送的数据。

简单来说,发送缓冲区存在的意义就是:接收方来不及接收了,我们暂时把它放在缓冲区保存,等对方来得及接收了,有接收能力了再发送给对方。

UDP套接字的接收缓冲区:由UDP给某个特定套接字排队的UDP数据报的数目受限于该套接字接收缓冲区的大小,但是这个缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致。如果缓冲区满了,再到达的UDP数据就会被丢弃。

UDP没有发送缓冲区:

  • UDP是一种无连接的协议,它不提供可靠的数据传输保证。当应用程序调用sendto函数发送数据时,UDP协议会将数据直接传递给网络层,而不像TCP那样在发送缓冲区中排队等待确认。
  • 由于UDP不进行拥塞控制,也没有重传机制,因此发送操作通常是立即返回的,即使数据报可能还没有被完全发送到网络上。

UDP的接收缓冲区:

  • UDP的接收缓冲区存在于内核中,用于暂存从网络层接收到的UDP数据报。
  • 由于UDP协议的性质,接收缓冲区不能保证数据报的顺序与发送顺序一致。数据报可能会因为网络延迟、路由差异等原因而以不同的顺序到达。
  • 如果接收缓冲区满了,新到达的数据报可能会被丢弃。UDP协议本身不会通知发送方数据报丢失,因此需要应用程序自行处理这种情况。

应用注意事项:

  • 应用程序在使用UDP时应该考虑到数据报可能会丢失、重复或乱序。
  • 对于需要可靠传输的应用,开发者需要在应用层实现额外的机制,如确认、重传等。
  • 应用程序还应该考虑到接收缓冲区的大小,以避免在高速网络环境中因为缓冲区溢出而丢失数据。

UDP不是全双工的,但是可以实现全双工。

UDP的设计目标是简单和低开销。全双工通信需要更多的控制信息和状态维护,这会增加复杂性,与UDP的设计目标相违背。全双工通信通常需要保持一定程度的连接状态。

全双工通信需要处理诸如流量控制、拥塞控制和数据包顺序等问题,UDP将这些责任交给了应用程序,自己则保持简单,只提供数据报文的发送和接收功能。如果UDP是全双工的,那么它需要在网络堆栈中为每个通信对维护更多的资源,例如缓冲区和状态信息。UDP的设计意图是尽量减少这种资源的使用。

注:UDP协议中使用connect会改变原来套接字绑定的目标地址和端口号,用新绑定的地址和端口号代替,原有的绑定状态会消失。与TCP不同,UDP的connect调用不会与目标地址进行任何形式的握手或建立连接。它仅仅是在套接字上设置了一个默认的目的地址。

UDP服务器接收数据的方式,以及是否能够同时接收来自多个客户端的数据

UDP是一种无连接的协议,它不保证数据的可靠传输,也不要求在数据传输之前建立连接。

接收数据的情况:

  • 服务器使用recvfrom系统调用等待接收数据。
  • recvfrom会阻塞当前线程,直到接收到客户端发送的数据。
  • 一旦接收到数据,服务器就会记录日志,并将接收到的数据处理后发送回客户端。

UDP协议支持多播广播,这也是其能够同时接收来自多个客户端的原因之一:

  • 广播:通过广播,服务器可以在本地网络中向所有客户端发送数据,所有客户端也可以通过广播向服务器发送消息。
  • 多播:多播允许服务器订阅一个特定的多播组,然后任何加入这个组的客户端都可以向该组发送消息,服务器接收来自组内所有客户端的数据。

这种能力意味着UDP不仅可以通过单播与多个客户端通信,也可以通过广播和多播机制同时处理来自多个客户端的数据报。关于多个客户端同时发送数据:

  • 由于UDP是无连接的,服务器不需要为每个客户端维持一个单独的连接,因此服务器可以同时处理来自多个客户端的数据。无论有多少客户端向同一个服务器地址发送数据包,服务器都可以使用相同的recvfrom()函数接收来自不同客户端的数据包。
  • 当服务器调用recvfrom时,如果多个客户端几乎同时发送数据,操作系统内核的网络栈会处理这些数据报。也可能会接收到来自不同客户端的数据,这取决于内核调度和网络状况。

因此,UDP服务器能够由多个客户端同时发送数据,而不会像TCP那样需要为每个客户端建立一个独立的连接。

注意点:

  • 由于UDP不保证数据的可靠传输,如果网络状况不佳或者数据报丢失,服务器可能不会收到某些客户端发送的数据。
  • recvfrom每次调用只处理一个数据报,如果多个数据报同时到达,它们会在内核中的队列中排队等待处理。

也就是说,UDP服务器能够同时接收来自多个客户端的数据,因为UDP协议本身支持多播和广播,并且在单个套接字上可以接收来自不同发送者的数据报。


四、UDP网络编程

UDP协议的服务器端程序设计的流程分为套接字建立、套接字于地址进行绑定、收发数据、关闭套接字等过程,分别对应函数socketbindsendtorecvfromclose

在这里插入图片描述

服务器端:建立套接字过程使用 socket 函数,建立的套接字类型为数据报套接字。地址结构与套接字文件描述符进行绑定。当绑定操作成功后,可以调用recvfrom函数从建立的套接字接收数据或者调用 sendto函数向建立的套接字发送络数据。当相关的处理过程结束后,调用 close函数关闭套接字。

  1. 创建UDP套接字得到套接字描述符
  2. 设置服务器地址和侦听端口
  3. 绑定套接字到侦听端口
  4. 接收客户端发送的数据
  5. 处理接收到的数据
  6. 发送响应给客户端
  7. 关闭套接字

客户端:套接字建立、收发数据、关闭套接字等过程,分别对应于函数 socketsendtorecvfromclose。建立套接字过程使用 socket函数。建立套接字之后,可以调用函数sendto向建立的套接字发送数据或者调用 recvfrom 函数从建立的套接字收网络数据。当相关的处理过程结束后,调用 close函数关闭套接字。

  1. 创建UDP套接字
  2. 设置服务器地址和端口
  3. 发送数据到服务器
  4. 接收服务器的响应
  5. 关闭套接字

UDP服务器可以在使用单个进程的情况下处理所有客户。对于UDP套接字,UDP层隐含有排队发生,即每个UDP套接字都有一个接送缓冲区,到达该套接字的每个数据报都进入这个套接字接收缓冲区。这样,在进程能够读该套接字中任何已排好队的数据报之前,如果有多个数据到达该套接字,那么相继到达的数据报仅仅加到该套接字的接收缓冲区中。然而这个缓冲区的大小是有限的。

在这里插入图片描述

上图中仅有一个服务器进程,它仅有的单个套接字用于接收所有到达的数据报并返回所有的响应。该套接字只有一个缓冲区来存放所到达的数据报。

如果一个客户数据报丢失,客户端将永远阻塞在recvfrom调用处,等待一个永远收不到的服务器应答。防止这种永久阻塞的方法一般是客户的recvfrom调用设置一个超时。

客户端必须给sendto调用指定服务器的端口号和IP地址。一般来说,客户端的IP地址和端口号都是由内核自动选择。即客户端不需要调用bind。客户端的IP地址却可以随客户发送的每一个UDP数据报而变动。

在这里插入图片描述

如果客户主机是多宿的(即具有多个网络接口和多个IP地址),那么在发送UDP数据报时,客户有可能在两个目的地之间交替选择。默认情况下,如果未明确指定,则操作系统会选择默认的发送接口,这通常是系统的路由表决定的。
号和IP地址。一般来说,客户端的IP地址和端口号都是由内核自动选择。即客户端不需要调用bind。客户端的IP地址却可以随客户发送的每一个UDP数据报而变动。

在这里插入图片描述

如果客户主机是多宿的(即具有多个网络接口和多个IP地址),那么在发送UDP数据报时,客户有可能在两个目的地之间交替选择。默认情况下,如果未明确指定,则操作系统会选择默认的发送接口,这通常是系统的路由表决定的。

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

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

相关文章

HTTP中的Cookie与Session

一、背景 HTTP协议是无状态无连接的。 无状态:服务器不会保存客户端历史请求记录,每一次请求都是全新的。 无连接:服务器应答后关闭连接,每次请求都是独立的。 无状态就导致服务器不认识每一个请求的客户端是否登陆过。 这时…

【贪心算法】贪心算法

贪心算法简介 1.什么是贪心算法2.贪心算法的特点3.学习贪心的方向 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃😃 1.什么是贪心算法 与其说是…

Spring为什么要用三级缓存解决循环依赖?

Spring为什么要用三级缓存解决循环依赖? 1. Spring是如何创建一个bean对象2. Spring三级缓存2.1 一级缓存:单例池,经历过完整bean生命,单例Bean对象2.2 二级缓存:提前暴露的Bean2.3 三级缓存:打破循环 3. S…

计算机网络通关学习(一)

简介 之前我通过王道的考研课进行了计算机网络的学习,但是在秋招准备过程中发现之前的笔记很多不足,学习的知识不够深入和巩固,所以再重新对《图解HTTP》&《图解TCP/IP》进行深度学习后,总结出了此篇博客,由于内容…

08_Python数据类型_字典

Python的基础数据类型 数值类型:整数、浮点数、复数、布尔字符串容器类型:列表、元祖、字典、集合 字典 字典(Dictionary)是一种可变容器模型,它可以存储任意类型对象,其中每个对象都存储为一个键值对。…

存储数据的树形结构

目录 1、二叉查找树 2、平衡二叉树AVL Tree 3 、平衡多叉树B-Tree 4、BTree树 5 、红黑树 红黑树的应用 6.平衡树的旋转 mysql 索引数据结构: Btree 索引是B树在数据库中的一种实现,最为常见的。B树 中的B代表平衡,而不是二叉 1、二…

带你如何使用CICD持续集成与持续交付

目录 一、CICD是什么 1.1 持续集成(Continuous Integration) 1.2 持续部署(Continuous Deployment) 1.3 持续交付(Continuous Delivery) 二、git工具使用 2.1 git简介 2.2 git的工作流程 2.3 部署g…

如何用 Scrapy 爬取网站数据并在 Easysearch 中进行存储检索分析

做过数据分析和爬虫程序的小伙伴想必对 Scrapy 这个爬虫框架已经很熟悉了。今天给大家介绍下,如何基于 Scrapy 快速编写一个爬虫程序并利用 Easysearch 储存、检索、分析爬取的数据。我们以极限科技的官网 Blog 为数据源,做下实操演示。 安装 scrapy 使…

3. Python计算水仙花数

Python计算水仙花数 一、什么是水仙花数? 百度答案 二、怎样使用Python计算水仙花数? 这里需要for循环,if判断,需要range()函数,需要知道怎么求个位数,十位数,百位数… 1. For循环 语句结…

CTFHub技能树-SQL注入-整数型注入

一、手动注入 思路:注入点->库->表->列->数据 首先使用order by探测有几列 http://challenge-215beae2f0b99b12.sandbox.ctfhub.com:10800/?id1 order by 2 我们发现order by 2 的时候有回显,到了order by 3 的时候就没有回显了&#xf…

k8s的环境配置

一、前期系统环境准备 准备3台主机:硬盘50G cpu2个 内存2G 1、3台主机同时配置 1)关闭防火墙与selinux、NetworkManager [rootk8s-master ~]# systemctl stop firewalld[rootk8s-master ~]# systemctl disable firewalldRemoved symlink /etc/systemd/…

CSS---序号使用css设置,counter-reset、counter-increment、content配合实现备注文案的序号展示

直接上代码&#xff0c;全代码copy即可使用! <template><div class"reminder"><span class"Bold_12_body" style"line-height: 8vw">温馨提示&#xff1a;</span><br /><div class"rule-container"…

【Hot100】LeetCode—84. 柱状图中最大的矩形

目录 1- 思路题目识别单调栈 2- 实现⭐84. 柱状图中最大的矩形——题解思路 3- ACM 实现 原题链接&#xff1a;84. 柱状图中最大的矩形 1- 思路 题目识别 识别1 &#xff1a;给定一个数组 heights &#xff0c;求解柱状图的最大面积 单调栈 使用 Stack 来实现&#xff0c;遍…

go语言中的数组指针和指针数组的区别详解

1.介绍 大家知道C语言之所以强大&#xff0c;就是因为c语言支持指针&#xff0c;而且权限特别大&#xff0c;c语言可以对计算机中任何内存的指针进行操作&#xff0c;这样自然而然也会带来一些不安全的因素&#xff0c;所以在golang中&#xff0c;「取消了对指针的一些偏移&…

【C语言】分支和循环专题应用

分支和循环专题应用 1、随机数生成1.1rand1.2 srand函数介绍1.3 time函数介绍1.4 设置随机数的范围 2、猜数字游戏的代码及实现 通过了分支和循环的介绍学习之后&#xff0c;我们可以运用分支和循环语句写出一些有趣的代码了&#xff0c;让我们来一起探索吧&#xff01; 写一个…

node.js 中的进程和线程工作原理

本文所有的代码均基于 node.js 14 LTS 版本分析 概念 进程是对正在运行中的程序的一个抽象&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;操作系统的其他所有内容都是围绕着进程展开的 线程是操作系统能够进行运算调度的最小单位&#xff0c;其是进程中的一个执…

远程桌面内网穿透是什么?有什么作用?

远程桌面内网穿透指的是通过特定技术手段&#xff0c;将处于内网中的电脑或服务器&#xff0c;通过外部网络&#xff08;互联网&#xff09;进行访问。内网穿透的主要作用是解决在内网环境下&#xff0c;远程设备与外部互联网之间的连接问题&#xff0c;允许用户从外部访问内网…

.Net Gacutil工具(全局程序集缓存工具)使用教程

GAC介绍&#xff1a; GAC&#xff08;Global Assembly Cache&#xff09;全局程序集缓存&#xff0c;是用于存放.Net应用程序共享的程序集。 像平常我们在Visual Studio中引用系统程序集时&#xff0c;这些程序集便来自于GAC。 GAC默认位置为&#xff1a;%windir%\Microsoft…

【ArcGIS】栅格计算器原理及案例介绍

ArcGIS&#xff1a;栅格计算器原理及案例介绍 栅格计算器&#xff08;Raster Calculator&#xff09;原理介绍案例案例1&#xff1a;计算栅格数据平均值 参考 栅格计算器&#xff08;Raster Calculator&#xff09;原理介绍 描述&#xff1a;在类似计算器的界面中&#xff0c;…

基于对数变换的图像美白增强,Matlab实现

博主简介&#xff1a;matlab图像处理&#xff08;QQ:3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于对数变换的图像美白增强&#xff0c;用matlab实现。 一、案例背景和算法介绍 这次案例是美白算法&…