当前位置: 首页 > news >正文

【Linux】UDP协议

文章目录

  • 📖 前言
  • 1. 再谈端口号
    • 1.1 端口号划分范围:
    • 1.2 端口和进程的关系:
      • 1.2 - 1 netstat
      • 1.2 - 2 pidof
    • 1.3 源端口和目的端口:
  • 2. UDP协议
    • 2.1 UDP协议格式:
  • 3. 再谈write/read
  • 4. UDP需要接收/发送缓冲区吗
  • 5. UDP使用注意事项

📖 前言

在我们刚学习网络时,我们知道网络是层状的结构,前面所有的内容都是围绕着应用层展开的。
接着我们来学习操作系统内部最顶层协议,叫做传输层协议。
应用层用应用的功能都是传输层提供的接口。

例如,用http通信,http协议底层用的是tcp协议。
https在密钥协商之前,首先要将客户端和服务端的连接建立好,所以在应用层的理解之下,还要搞一下传输层协议。

传输层最典型协议有两种,一个udp,以个tcp,对应的就是曾经学到的udp套接字和tcp套接字。

👉 网络层状结构复习


1. 再谈端口号

端口号(Port)标识了一个主机上进行通信的不同的应用程序。

在写套接字的时候,无论udp还是tcp,在服务器启动时都必须bind,得明确服务端的端口号,一旦保存端口号,底层在收到报文时,操作系统在收到数据,会根据对应的报文来进行数据处理,根据端口号将数据推送到特定的服务中。

在这里插入图片描述

这四个概念非常重要:在TCP / IP协议中,用 “源IP”,“源端口号”,“目的IP”,“目的端口号”。

端口号的位数是16位端口号:

  • 为什么在应用层写套接字时,对应的端口号是16位呢?
    • 因为tcpudp它的报头当中,端口号的字段就是16位的。
    • 也就是说在内核里面端口号就是16位。
  • 所以在应用层使用系统接口时,传入的端口号也只需要16位就够了。

1.1 端口号划分范围:

端口号和服务是一一对应的。

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

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

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

查看知名端口号:

cat /etc/services

所以在自己写一个程序使用端口号时,要避开这些知名端口号,避免不必要的麻烦。

这些端口是被特定的服务所采用的:

在这里插入图片描述
是因为有这个后端的守护进程sshd,一直在后端运行,所以在本地打开X-shelI时,连接的就是这个服务,由这个服务来帮助我们登录Linux。

1.2 端口和进程的关系:

端口号是用来标定进程唯一性的。

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

  • 这是一个经典的问题,因为端口号是用来标定进程唯一性的。
  • 所以一个端口号只能对应一个进程,而一个进程是可以对应多个端口号的!

一个进程可以同时监听和处理多个端口号上的网络数据。

1.2 - 1 netstat

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

netstat是一个用于显示网络连接、路由表和网络接口等信息的常用命令。它可以在命令行界面下运行,并提供了多种选项来获取特定类型的网络统计数据。

查看网络状态:

netstat [选项]

常用选项:

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

1.2 - 2 pidof

在查看服务器的进程id时非常方便。

pidof是一个用于查找指定进程名称所对应的进程ID的命令。在 Linux系统中,可以使用这个命令来获取特定进程的PID(进程 ID),以便进行后续处理。

通过进程名,查看进程id:

pidof [进程名]

常用选项:

  • -s:只返回一个进程 ID(如果有多个匹配结果)。
  • -x:同时匹配进程名和命令行参数,而不仅仅是进程名。
  • -o:仅返回指定用户运行的进程 ID。
  • -c:只返回匹配的进程数量,而不返回进程 ID。

1.3 源端口和目的端口:

  • 源端口(Source Port)是指发送数据包的应用程序或进程所使用的端口号:
    • 在计算机通信中,数据从源端发送到目的端时,需要通过网络传输,源端口用于标识发送方应用程序或进程。
  • 目的端口(Destination Port)是指接收数据包的应用程序或进程所使用的端口号:
    • 当数据包到达目的地后,通过目的端口将数据包传递给相应的应用程序或进程。

源端口和目的端口组合在一起形成一个套接字(Socket),在网络中充当数据交换的门户。通过源端口和目的端口的配对,可以确保数据包被正确地发送和接收,并且能够正确地路由到目的地。

在传输层协议中,如TCP(传输控制协议)和UDP(用户数据报协议),源端口和目的端口信息包含在数据包的首部中,用于标识通信双方的应用程序或进程。通过源端口和目的端口的匹配,网络设备可以将接收到的数据包正确地路由和交付给相应的应用程序或进程。


2. UDP协议

我们之前用UDP协议写过一个简单的聊天程序:👉 UDP的服务端 + 客户端。

  • 我们再来回顾一下UDP的一组概念:

未来学习的所有协议必须考虑两个共性问题:

  1. 如何封装和解包?
  2. 如何分用?

在我们之前网络基础中讲到过封装解包和分用的过程,👉 复习传送门。

我们以UDP为例:

  • 封装:
    • udp当上层应用调用sendto,要发送信息。
    • 在传输层添加udp报头时,就是给原始数据前面再写上8字节数据就可以了(报头一加)。
    • udp采用的是定长报文。
  • 解包:
    • 收到消息之后,只需要提取前8个字书就是报头。
    • 剩下的就是报文的有效载荷了。
  • 分用:
    • udp上面还有应用服务,那么udp收到报文之后,它如何知道要将报文转发给上层的哪一个应用呢?
    • 源端口和目的端口!!

UDP的特点:

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

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

udp一定不会是为了可靠性而做过多的设计!

udp不可靠,报文丢了就是真的丢了。丟包了不重要,因为允许丢包。

面向数据报:

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

  • udp要么不收报文,要么收到的就是一个完整的报文。
  • 因为有udp长度和校验和保证。
  • 报文有自己的报头长度和总长度。
  • 当收到了一批二进制,可以正常的去提取一个一个的完整的udp报文。
  • 面相数据报的通信方式有点像寄信,寄了十封信,就能够收到十封信,信和信用信封分开来。

假设用UDP传输100个字节的数据:

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

2.1 UDP协议格式:

在这里插入图片描述
UDP(User Datagram Protocol)的报头长度固定为8个字节。

网络协议栈的tcp/ip协议,是内核中实现的,内核是用C语言实现的,报头本质上也是一个对象。

假设报头代码是如下(并非源码实现):

struct udp_hdr
{unsigned int src_port : 16;unsigned int dst_port : 16;unsigned int udp_len : 16;unsigned int udp_check : 16;
};

udp报头类型C语言中称之为位段。

添加报头的本质,其实就是拷贝对象!

这些字段全都是位段,给数据添加报头就是把对应的位段的对象一定义,属性一填,然后把对象拷贝到属性的前面,最后就形成一个报文。

16位UDP长度是UDP报文整体的长度(单位Byte):

  • 16位UDP长度,表示整个数据报(UDP首部 + UDP数据)的最大长度。
  • 16位UDP检验和,主要是为了防止报文当中有些字段出现一些偏差,需要进行校验。
  • 如果校验和出错,就会直接丢弃!!

UDP叫做面向数据报,体现在它不是流式的,报文和报文有明显边界。

16位UDP检验和:

  • 如果UDP校验和失败了,说明数据是有问题的。
  • 如果校验和出错,就会直接丢弃报文数据。

3. 再谈write/read

之前我们学习过操作系统的文件操作的write/read接口,我们在使用者的身份来看,只看到了最后的结果,但是详细的过程我们真的清楚吗?下面我们看看下面过程。

  • 文件中,我们把数据通过文件描述符写到文件当中:
  • 其实并不是把数据写到了磁盘当中的特定文件。
  • 而是把数据写给了操作系统的缓冲区里,然后操作系统再根据它自己的策略将数据刷新到外设,比如磁盘上。
  • 所以之前学习文件时的write函数不能叫做将数据写入到磁盘,而应该叫做拷贝函数。
  • 先将应用层数据拷贝到内核,再由操作系统定向的根据自己的策略进行IO,更新到磁盘上。
  • 调用writesendto这样的系统接口,并没有把数据发送到网络里,而是把数据交给了操作系统:
  • 真正发送数据不是我们发的,而是我们将数据交给操作系统,让操作系统帮我们发的。
  • 所以我们之前写的所有的网络或者文件的接口,根本就不能叫做发送和写入接口,而应该叫做拷贝函数。
  • 所以我们在学习网络中,大部分用套接字发送的数据,其实根本就没有发送数据,而只是将数据拷贝到了一个叫tcpudp所对应的缓冲区中!!

数据什么时候发,怎么发这个工作就由操作系统来决定了。

4. UDP需要接收/发送缓冲区吗

  • UDP没有也不需要发送缓冲区:
  • 因为数据太简单了,上层拷贝的数据到了内核。
  • 内核添加八个字节的报头,三四个字段一填。
  • 填完之后,操作系统直接将报文交给了网络协议栈。
  • 到了网络层,后续就是ip的任务了。
  • 不需要维护可靠性,不需要将数据暂存起来。
  • 只需要将数据交给内核这个工作就完了。

发送的时候直接交给操作系统,操作系统直接向上交付,速度很快不需要缓冲区。所以就不需要真正的发送缓冲区。

UDP 在发送端不一定需要显式的发送缓冲区,但通常会由操作系统提供一个临时的缓冲区来保存待发送的数据。

  • UDP需要接收缓冲区吗?需要!!
  • 作为udp在进行数据接收的时候,当底层数据没就绪时,在应用层的表现就是recvfrom接口是阻塞的。
  • 一直卡在那里当底层数据就绪时,recvfrom接口才会返回,并将数据拷贝到提前设置到recvfrom的缓冲区里面。

如果udp收到了数据,操作系统压力很大,收到了数据还没来得及调度这个进程(应用层进程来不及接收数据),如果内核不存在接收缓冲区,一定会出现数据的丢失问题。

udp是不保证可靠性,但是并不代表它可以在可靠性这件事上肆意妄为:(重点)

  • 如果没有接收缓冲区,一旦应用层进程来不及接收数据,这个数据直接就丢了!
  • 所以udp是具备接收缓冲区的,数据收到之后,如果上层来不及处理。
  • 会暂时保存在缓冲区里,等到应用层来得及读取了,再把数据从缓冲区里拷过去。

然尽管UDP协议本身没有应用层缓冲区,但在实际应用中,很多基于UDP的应用程序会在应用层上实现自己的缓冲机制。这是为了解决数据传输中可能出现的丢包、乱序等问题。应用层缓冲区可以用来存储接收到的数据包,以便应用程序按照自己的需求进行处理、重组或重发等操作。
需要注意的是,应用层缓冲区是由应用程序自己实现和管理的,不同的应用程序可能有不同的缓冲策略和机制。使用UDP协议时,开发者需要在应用程序中自行管理缓冲区,确保数据的完整性和正确性。

UDP报文乱序到达:

  • udp不保证可靠性,就导致了数据不能够按序到达。
  • 虽然有接收缓冲区,但是接收缓冲区里数据的顺序性,upd和操作系统不关心。
  • 应用层用户若是关心接收数据的顺序,就要采取响应措施,如应用层用户对数据报文编号,重排序。
  • 如果接收缓冲区满了的话,再来数据,再到达的udp数据就会被丢弃了。

UDP协议本身并没有提供应用层缓冲区。UDP是一种无连接的、不可靠的传输协议,它将数据封装成数据包,通过网络进行传输,不需要建立像TCP那样的连接。
在UDP通信中,数据包从发送方直接发送到目的地,如果发生丢包或乱序等情况,UDP协议本身不提供任何机制来处理这些问题。因此,UDP不具备对数据包的重组、重发和流量控制等功能。

UDP的socket既能读也能写,UDP报文出的路径和报文进的路径是两条路径,互相不干扰,所以是全双工。


5. UDP使用注意事项

UDP协议首部是一个16位的最大长度(单位Byte),也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部2^16 个 Byte + 8 Byte )。

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

udp存在的意义:

  • 现在的网络环境一般不丢包,如果丢包丢掉一些某些场景不影响。
  • 因为udp很简单,不需要维护复杂连接,所以也是需要在各种不同的场景中被采用的。
  • 其中最经典的场景就是直播。
    • 观看直播时,模糊卡顿掉帧等情况是允许的。
    • 因为观看直播的人太多了,每个人都要维护连接,服务器扛不住。
    • 如果推送的是udp,不用建立连接,谁需要就给谁。

相关文章:

【Linux】UDP协议

文章目录 📖 前言1. 再谈端口号1.1 端口号划分范围:1.2 端口和进程的关系:1.2 - 1 netstat1.2 - 2 pidof 1.3 源端口和目的端口: 2. UDP协议2.1 UDP协议格式: 3. 再谈write/read4. UDP需要接收/发送缓冲区吗5. UDP使用…...

AutoCAD 2022 for Mac/Windows升级您的设计工具,提升工作效率

Autodesk AutoCAD 2022 是设计行业最流行的计算机辅助设计 (CAD) 软件之一。这款软件由Autodesk公司开发,它提供了强大的功能,从基本的设计和修改工具,到复杂的3D建模和渲染,一切尽在掌握。通过其直观的用户界面和不断更新的功能&…...

协程,GIL全局解释器,互斥锁,线程池,Concurrent模块

进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。 Python对并发编程的支持 (1)多线程:threading,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成。 (2)多进程:multiproces…...

MAPEFFECT代码在传奇中有何作用如何运用

今天介绍一下MAPEFFECT的作用和使用方法,可以实现的效果比如进入游戏或者某个地图显示特效,或者显示地图名称,提示信息等等用到的命令就是MAPEFFECT。 使用方法是 在QManage.txt中找到 [Startup] 在下面增加如下代码 #if #act MAPEFFECT 11…...

Godot 官方2D C#重构(1):雪花碰撞

前言 Godot 官方 教程 Godot 2d 官方案例C#重构 专栏 Godot 2d 重构 github地址 实现效果 难点介绍 Godot GDScript和C# 对应关系大部分靠猜 文件导入 资源地址:默认为res://开头2D贴图导入类型:Texture2D public Texture2D Bullet_Image new Textu…...

计算机基础知识35

进程和线程的比较 1. 进程的开销比线程的开销大很多 2. 进程之间的数据是隔离的,但是,线程之间的数据不隔离 3. 多个进程间的线程数据不共享----->让进程通信(IPC)---->进程下的线程也通信了---->队列 GIL全局解释器锁(重要理论) # 虽然一个进程…...

VulnHub mrRobot

一、信息收集 1.访问地址 没啥信息,尝试扫下目录 2.目录扫描 key1 发现有wp-admin/和robots.txt robots.txt里面还拿到了一个密码字典,猜测是爆破wp的网站账号密码的 3.访问wp-admin/ ┌──(root💀kali)-[~/桌面] └─# sort -u fsoci…...

【MATLAB第79期】基于MATLAB的数据抽样合集(sobol、LHS、Halton、正交、随机函数)更新中

【MATLAB第79期】基于MATLAB的数据抽样合集(sobol、LHS、Halton、正交、随机函数)更新中 一、随机函数 1.指定区间随机生成数据(小数) [a b]区间随机数生成: Aa(b-a)rand(m,n) m:待生成矩阵A的行数 n: 待生成矩阵A…...

Lua快速入门教程

文章目录 1、Linux安装Lua2、语法练习2.1、变量2.2、循环2.3、函数2.4、数组2.5、迭代器2.6、Table操作2.7、Lua 模块与包2.8、加载机制2.9、Lua 元表(Metatable) 3、Lua 协同程序(coroutine)4、文件IO操作4.1、简单模式4.2、完全模式 5、错误处理 内容来源菜鸟教程&#xff0c…...

html资源提示符

前言&#xff1a;正常dom解析 中遇到script标签 &#xff0c;会暂停主线程 去下载js&#xff0c;拿到资源后&#xff0c;主线程再执行js。 那么主线程在等待网络线程下载这个空闲很浪费 解决方案&#xff1a; script标签增加属性 async defer 1.async <script src"./i…...

VR智能家居虚拟连接仿真培训系统重塑传统家居行业

家居行业基于对场景的打造及设计&#xff0c;拥有广阔前景&#xff0c;是众多行业里面成为最有可能进行元宇宙落地的应用场景之一。 家居行业十分注重场景的打造及设计&#xff0c;而元宇宙恰恰能通过将人工智能、虚拟现实、大数据、物联网等技术融合提升&#xff0c;带来身临其…...

Defects4j数据集安装及使用

0、常见问题 1. 所有配置完成后运行defects4j info -p Lang测试出现错误 Cant locate DBI.pm in INC (you may need to install the DBI module) (INC contains: /myproject/defects4j/framework/lib /myproject/defects4j/framework /myproject/defects4j/framework/core /m…...

vant_ CountDown倒计时

语法可以直接在官网查看 需求 后端返回的数据格式如下 [{"id": 1,"btn_text": "1","second": 0},{"id": 2,"btn_text": "1","second": 0}... ]之前约定second最多30s&#xff0c; 因此只需…...

spark集成hive

集群使用ambarihdp方式进行部署,集群的相关版本号如下所示: ambari版本 Version 2.7.4.0 HDP版本 HDP-3.1.4.0 hive版本 3.1.0 spark版本 2.3.0 集群前提条件: 1.Hdp、Spark、Hive都已部署好 2.Hive数据层建好&#xff0c;在Hdfs生成相应各层目录&#xff0c;后面配…...

提升微服务稳定性与性能:深入剖析Netflix Hystrix框架

说到 Netflix Hystrix 框架&#xff0c;一定离不开 com.netflix.hystrix.HystrixCommand&#xff0c;这个类是 Netflix 开源的 Hystrix 框架中的一个关键类&#xff0c;用于实现服务的容错和熔断功能。它主要用于将远程服务调用封装成一个独立的命令对象&#xff0c;以便于进行…...

IT运维管理系统在国有大型企业网络中的应用和可以解决的问题

随着国有大型企业业务的快速发展&#xff0c;网络运维管理面临着诸多挑战。本文将从问题概述、解决方案、监控易优势、实际案例和总结等方面阐述IT运维管理系统在国有大型企业网络中的应用和可以解决的问题。​IT运维管理系统&#xff1a;国有大型企业网络的变革者与解决之道 一…...

嵌入式实时操作系统的设计与开发 (线程操作学习)

在aCoral操作系统中&#xff0c;线程退出采用了和Linux一样的方式&#xff0c;线程函数不用死等或显示调用退出相关函数&#xff0c;也就是说用户不用担心函数执行完后的事情。 uc/OS II任务函数与退出 void test(void *ptr){Do_something();while(1); }void test(void *ptr)…...

竞赛 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…...

【RTOS学习】同步与互斥 | 队列

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 同步与互斥 | 队列 &#x1f349;同步与互斥&#x1f366;同步&#x1f366;互斥 &#x1f349;队…...

Python订单生成器+队列+异步提高性能和容错

以下代码实现了一个订单生成器&#xff0c;使用 asyncio 和 aioredis 库实现了高并发地生成订单&#xff0c;并将新增订单异步更新到数据库。具体实现流程如下&#xff1a; 初始化 OrderGenerator 类。传入 Redis 服务器地址和并发数&#xff0c;在初始化函数中设置并发数和一…...

理德名人故事:全球投资之父-约翰.邓普顿

说到约翰‧邓普顿&#xff0c;我们就会想到他的很多标签。比如全球投资之父、史上最成功的基金经理等等。他是邓普顿集团的创始人&#xff0c;一直被誉为全球最具智慧以及最受尊崇的投资者之一。福布斯资本家杂志称他为"全球投资之父"及"历史上最成功的基金经理…...

微前端三:qiankun 协作开发和上线部署

我们先看qiankun怎么上线部署&#xff1a; 我这边用的是yaml 文件在 rancher上部署的&#xff1a; base是基座&#xff0c;这里每个应用都是一个服务&#xff0c;这个还是跟之前一样并没有区别&#xff0c;那如何在一个域名上挂载多个服务呢&#xff1f; 最开始我们主要是在in…...

HTML三叉戟,标签、元素、属性各个的意义是什么?

&#x1f31f;&#x1f31f;&#x1f31f; 专栏详解 &#x1f389; &#x1f389; &#x1f389; 欢迎来到前端开发之旅专栏&#xff01; 不管你是完全小白&#xff0c;还是有一点经验的开发者&#xff0c;在这里你会了解到最简单易懂的语言&#xff0c;与你分享有关前端技术和…...

prometheus获取kubelet接口监控数据

一、前言 k8s集群的kubelet服务内部有自带的cadvisor服务用于收集k8s集群的监控数据&#xff0c;所以可以通过调用kubelet的接口就能获取pod的资源监控数据&#xff0c;在新版本的k8s中&#xff0c;kubelet的监控数据获取端口为10250端口&#xff0c;老版本的是10255端口 二、…...

国产主控应用案例:汉王电子血压计-君正开发板

2023春季新品发布会上汉王科技发布柯氏音法电子血压计产品—汉王电子血压计&#xff0c;继嗅觉检测盒之后再次深度布局大健康领域。 不同于当前市面上使用示波法原理的电子血压计&#xff0c;汉王电子血压计采用血压测量金标准中的柯氏音法&#xff0c;由此引领一场电子血压计领…...

万宾科技智能井盖传感器特点介绍

当谈论城市基础设施的管理和安全时&#xff0c;井盖通常不是第一项引人注目的话题。然而&#xff0c;传统井盖和智能井盖传感器之间的差异已经引起了城市规划者和工程师的广泛关注。这两种技术在功能、管理、安全和成本等多个方面存在着显著的差异。 WITBEE万宾智能井盖传感器E…...

YoloV8改进策略:SwiftFormer,全网首发,独家改进的高效加性注意力用于实时移动视觉应用的模型,重构YoloV8

文章目录 摘要论文:《SwiftFormer:基于Transformer的高效加性注意力用于实时移动视觉应用的模型》1、简介2、相关研究3、方法3.1、注意力模块概述3.2、高效的加性注意力3.3、SwiftFormer 架构4、实验4.1、实现细节4.2、基线比较4.3、图像分类4.4、目标检测和实例分割4.5、语义…...

Jupyter Notebook在指定位置打开

1、在Jupyter Notebook设置文件中修改默认路径 anconda prompt输入&#xff1a; jupyter notebook --generate-config 找到配置文件路径&#xff1a;C:\Users\Lenovo.jupyter 打开文件&#xff0c;修改默认路径&#xff1a; ## The directory to use for notebooks and kernel…...

树控件的使用

目录 1、修改树控件的基础属性&#xff1a; 2、准备图标 &#xff1a; &#xff08;1&#xff09;、ico后缀的图片放入当前文件路径的rc中 &#xff08;2&#xff09;、在Icon中添加资源&#xff0c;导入图片 &#xff08;3&#xff09;、准备HICON图标 &#xff08;4&am…...

C++实现顺序栈类的定义,编写main ()函数验证顺序栈类设计的合理性

C实现顺序栈类的定义&#xff0c;编写main ()函数验证顺序栈类设计的合理性 以下是一个简单的C代码示例&#xff0c;用于实现顺序栈类的定义并编写main()函数来验证其合理性&#xff1a; #include <iostream> using namespace std;const int MAX_SIZE 100; // 定义栈的…...