【网络编程】二、UDP网络套接字编程详解
文章目录
- 前言
- Ⅰ. UDP服务端
- 一、服务器创建流程
- 二、创建套接字 -- socket
- socket 属于什么类型的接口❓❓❓
- socket 是被谁调用的❓❓❓
- socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓
- 三、绑定对应端口号、IP地址到套接字 -- bind
- 四、数据的发送和接收 -- `sendto` && `recvfrom`
- 五、搭建服务器框架
- ① 服务器类实现:udpserver.hpp
- ② 服务器主函数:udpserver.cpp
- 绑定INADDR_ANY的好处
- Ⅱ. UDP客户端
- 一、客户端创建流程
- 二、创建套接字
- 三、关于客户端的绑定问题
- 四、搭建客户端框架
- ① 客户端类单进程版实现(读写会互相阻塞):udpclient.hpp
- 💥② 客户端类多线程版实现(读写分离):udpclient.hpp
- ③ 客户端主函数:udpclient.cpp
- Ⅲ. 服务端加入业务处理
- 一、简单的中英文翻译
- 二、简单的远程命令行指令解析
- 三、简易的小聊天室
- Ⅳ. windows系统的客户端

前言
UDP
相当于 TCP
来说细节少了很多,所以我们先从简单的 UDP
套接字编程下手,因为其涉及到的细节比较少,也很直接,就是面向报文,服务端拿到信息就直接丢给客户端,丢了也不管,无需我们关系太多细节,等我们把 UDP
套接字编程稍微掌握了,其实 TCP
的那套接口也是类似的,但是我们学 TCP
的时候,需要去了解它的传输细节。
下面我们就从 UDP
套接字编程开始,分为服务端和客户端,我们先讲服务端,客户端也就顺其自然了解了!
Ⅰ. UDP服务端
一、服务器创建流程
- 创建套接字(
socket
) - 绑定端口号和
IP
地址(一般来说端口号是固定的,而IP
地址就作为服务器来说,我们设置为0.0.0.0
或者INADDR_ANY
,表示任意IP
都能访问) - 接收(
recvfrom
)、发送(sendto
)数据,包括对数据的业务处理
二、创建套接字 – socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int socket(int domain, int type, int protocol);
参数说明:
-
domain:创建套接字的域或者叫做协议家族,也就是创建套接字的类型。该参数就相当于
struct sockaddr
结构的前16
位。- 如果是本地通信就设置为**
AF_UNIX
**,如果是网络通信就设置为AF_INET
(IPv4
)或AF_INET6
(IPv6
)。
- 如果是本地通信就设置为**
-
type:创建套接字时所需的服务类型。
- 其中最常见的服务类型是
SOCK_STREAM
和SOCK_DGRAM
,如果是基于UDP
的网络通信,我们采用的就是**SOCK_DGRAM
**,叫做用户数据报服务,如果是基于TCP
的网络通信,我们采用的就是SOCK_STREAM
,叫做流式套接字,提供的是流式服务。
- 其中最常见的服务类型是
-
protocol:创建套接字的协议类别。
- 你可以指明为
TCP
或UDP
,但该字段 一般直接设置为0
就可以了,设置为0
表示的就是默认,此时会根据传入的前两个参数自动推导出你最终需要使用的是哪种协议。
- 你可以指明为
返回值说明:
- 套接字创建 成功返回一个文件描述符,创建失败返回
-1
,同时错误码会被设置。
socket 属于什么类型的接口❓❓❓
网络协议栈是分层的,按照 TCP/IP
四层模型来说,自顶向下依次是应用层、传输层、网络层和数据链路层。而我们现在所写的代码都叫做 用户级代码,也就是说我们是在应用层编写代码,因此我们调用的实际是下三层的接口,而传输层和网络层都是在操作系统内完成的,也就意味着我们在应用层调用的接口都叫做 系统调用接口。
socket 是被谁调用的❓❓❓
socket
这个函数是被程序调用的,但并不是被程序在编码上直接调用的,而是程序编码形成的可执行程序运行起来变成进程,当这个进程被 CPU
调度执行到 socket
函数时,然后才会执行创建套接字的代码,也就是说 socket
函数是被进程所调用的。
socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓
socket
函数是被进程所调用的,而每一个进程在系统层面上都有一个进程地址空间 PCB
(task_struct
)、文件描述符表(files_struct
) 以及对应打开的各种文件。而文件描述符表里面包含了一个数组 fd_array
,其中数组中的 0、1、2
下标依次对应的就是 标准输入、标准输出 以及 标准错误。
、
当我们调用 socket
函数创建套接字时,实际相当于我们打开了一个“网络文件”,打开后在内核层面上就形成了一个对应的 struct file
结构体,同时该结构体被连入到了该进程对应的文件双链表,并将该结构体的首地址填入到了 fd_array
数组当中下标为 3
的位置(除非此时先打开了其它文件描述符),此时 fd_array
数组中下标为 3
的指针就指向了这个打开的“网络文件”,最后该文件描述符作为 socket
函数的返回值返回给了用户。
其中每一个 struct file
结构体中包含的就是对应打开文件各种信息,比如文件的属性信息、操作方法以及文件缓冲区等。其中文件对应的属性在内核当中是由 struct inode
结构体来维护的,而文件对应的操作方法实际就是一堆的函数指针(比如 read*
和 write*
),它们在内核当中就是由 struct file_operations
结构体来维护的。而文件缓冲区对于打开的普通文件来说对应的一般是磁盘,但对于现在打开的 “网络文件” 来说,这里的文件缓冲区对应的就是网卡。
对于一般的普通文件来说,当用户通过文件描述符将数据写到文件缓冲区,然后再把数据刷到磁盘上就完成了数据的写入操作。而对于现在 socket
函数打开的 “网络文件” 来说,当用户将数据写到文件缓冲区后,操作系统会定期将数据刷到网卡里面,而网卡则是负责数据发送的,因此数据最终就发送到了网络当中。所以可以总结一点,网络中数据的通信,其实就是文件之间的拷贝!
三、绑定对应端口号、IP地址到套接字 – bind
现在套接字已经创建成功了,但作为一款服务器来讲,如果只是把套接字创建好了,本质上只是在系统层面上打开了一个文件,操作系统将来并不知道是要将数据写入到磁盘还是刷到网卡,此时该文件还没有与网络关联起来。
所以我们要绑定对应的端口号、IP
地址到套接字文件中,此时就可以改变网络文件当中文件操作函数的指向,将对应的操作函数改为对应网卡的操作方法,此时读数据和写数据对应的操作对象就是网卡了,所以绑定实际上就是将文件和网络关联起来。而绑定使用的函数就是 bind()
函数!
该函数的函数原型如下:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
- sockfd:套接字描述符,即要绑定的套接字。
- addr:一个指向
sockaddr
结构体的指针,该结构体包括协议家族、IP地址、端口号等。sin_family
:表示协议家族。sin_port
:表示端口号,是一个16
位的无符号整数。sin_addr
:表示IP
地址,是一个32
位的无符号整数。- 其中
sin_addr
的类型是struct in_addr
,实际该结构体当中就只有一个成员,该成员就是一个32
位的无符号整数,IP
地址实际就是存储在这个整数当中的。
- 其中
- addrlen:传入的
sockaddr
结构体的大小。
返回值说明:
- 绑定成功返回
0
,绑定失败返回-1
,同时错误码会被设置。
对于上面的参数
addr
来说,一般需要借助到我们之前讲的几个函数来转换格式:
- 一开始最好将该结构体初始化一下,也就是清空数据。
sin_port
需要转化为网络字节格式也就是大端格式,又因为它是16
位的,那么就得使用htons()
函数;sin_addr
中的s_addr
其实一般我们是给一个点分十进制字符串,然后通过inet_addr()
函数将其转化为网络字节序的32
位无符号整型,但是对于服务器来说没必要这么麻烦,因为IP
地址直接设为0.0.0.0
即可,表示任意IP
都能访问,所以直接用头文件中给的宏INADDR_ANY
。
总结起来就是这样子:
struct sockaddr_in local;
bzero(&local, sizeof local); // 先将一段local的内存清零,即将其中的每个字节都设置为0local.sin_family = AF_INET;
local.sin_port = htons(_port); // 因为端口号是多个字节组成,所以要保证先转化为大段序列
local.sin_addr.s_addr = INADDR_ANY;
关于
struct sockaddr_in
结构体,我们之前有谈过,我们可以用 grep 命令在/usr/include
目录下查找该结构,此时就可以找到定义该结构的文件。在该文件中就可以找到struct sockaddr_in
结构的定义,需要注意的是,struct sockaddr_in
属于系统级的概念,不同的平台接口设计可能会有点差别。/* Structure describing an Internet socket address. */ struct sockaddr_in {__SOCKADDR_COMMON (sin_);in_port_t sin_port; /* Port number. */struct in_addr sin_addr; /* Internet address. *//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)]; };/* Internet address. */ typedef uint32_t in_addr_t; struct in_addr {in_addr_t s_addr; };
四、数据的发送和接收 – sendto
&& recvfrom
UDP
套接字是无连接协议,必须使用 recvfrom
函数接收数据,sendto
函数发送数据!
因为我们之前说过,对于无连接的协议来说,最好就是用上面这两个接口,对于面向连接的协议则不同!
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
- 作用:该函数用于将数据报发送到指定的目的地。
- 参数:
sockfd
:表示要发送数据的套接字文件描述符。buf
:指向要发送的数据缓冲区。len
:表示要发送的数据长度。flags
:表示发送数据的选项,一般我们 设为 0 就行了!常用的有MSG_DONTWAIT
表示非阻塞发送。dest_addr
:(输入参数)指向目标地址的sockaddr
结构体指针,包括目标 IP 地址和端口号等信息。addrlen
:(输入参数)目标地址结构体的大小。
- 返回值:
- 如果发送成功,返回发送的字节数。
- 如果发送失败,返回
-1
,并设置errno
错误码。
需要注意的是,
sendto()
函数是阻塞型函数,如果要进行非阻塞型发送,可以设置MSG_DONTWAIT
标志或使用select()
函数等。同时,sendto()
函数在发送数据时不保证数据一定会被对方接收,如果需要保证数据可靠性,应该使用 TCP 协议。
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
-
作用:从已连接的
socket
中接收数据,并将数据存储到指定的缓冲区中。 -
参数:
-
sockfd
:已经建立好连接的socket
。 -
buf
:指向接收数据存放的缓冲区。 -
len
:缓冲区长度。 -
flags
:读取方式,一般设为0
,阻塞式读取。 -
src_addr
:(输出型参数)返回发送方的地址信息。 -
addrlen
:(输入输出型参数)地址信息的长度。
-
-
返回值:
- 成功接收到数据时,它会 返回接收到的字节数
- 失败返回值:发生错误,则返回
-1
,并设置errno
变量以指示错误类型。
五、搭建服务器框架
搭建服务器的细节都在注释中!
① 服务器类实现:udpserver.hpp
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "onlineUser.hpp"
using namespace std;namespace Server
{static const string defaultIP = "0.0.0.0"; // 默认设为0,表示接收任意IPstatic const int MAXSIZE = 1024; // 接收到的数据最大值enum { USAGE_ERR = 1, BIND_ERR, SOCKET_ERR, CLOSE_ERR, OPEN_ERR, NOTFOUND_ERR, SEND_ERR }; // 错误码using func_t = function<void(int, string, uint16_t, string)>; // 业务处理函数的类型class udpServer{private:uint16_t _port; // 当前服务端进程的端口号string _ip; // 当前服务端的ip,但是作为一个服务器,一般都是将ip设为全0,代表任意ip都能访问int _socketfd; // 套接字文件的文件描述符func_t _callback; // 服务端要完成的业务public:udpServer(func_t callback, const uint16_t port, const string& ip = defaultIP):_port(port), _ip(ip), _socketfd(-1), _callback(callback){}// 初始化服务端void initServer(){// 1. 创建套接字(本质是创建文件)_socketfd = socket(AF_INET, SOCK_DGRAM, 0);if(_socketfd == -1){cerr << "socket error: " << errno << " : " << strerror(errno) << endl; exit(SOCKET_ERR);}cout << "socket success: " << _socketfd << endl;// 2. 绑定端口号和ip地址到当前的套接字文件struct sockaddr_in local;bzero(&local, sizeof local); // 先将一段local的内存清零,即将其中的每个字节都设置为0,更推荐用memset函数!local.sin_family = AF_INET;local.sin_port = htons(_port); // 因为端口号是多个字节组成,所以要保证先转化为大段序列// inet_addr函数帮我们将格式化字符串转化为in_addr_t类型,并且调整成大段序列// local.sin_addr.s_addr = inet_addr(_ip.c_str()); // 但是一般我们将作为服务器的ip设为全0,所以不需要做上述工作,直接利用一个值为全0的宏赋值就行local.sin_addr.s_addr = INADDR_ANY;int n = bind(_socketfd, (struct sockaddr*)&local, sizeof local);if(n == -1){cerr << "bind error: " << errno << " : " << strerror(errno) << endl; exit(BIND_ERR);}}// 启动服务端void start(){// 服务器的本质就是一个死循环,称为常驻内存的进程char buffer[MAXSIZE];while(true){struct sockaddr_in src;socklen_t srclen = sizeof(src); // 这是因为操作系统不知道我们传过去的是哪个sockaddr的哪个结构体,所以我们要传大小过去// 这里要传sizeof(buffer)-1是因为腾出一个位置给\0ssize_t n = recvfrom(_socketfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&src, &srclen);if(n > 0){// 将接收到的客户端的信息保存起来uint16_t src_port = ntohs
相关文章:
【网络编程】二、UDP网络套接字编程详解
文章目录 前言Ⅰ. UDP服务端一、服务器创建流程二、创建套接字 -- socketsocket 属于什么类型的接口❓❓❓socket 是被谁调用的❓❓❓socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓三、绑定对应端口号、IP地址到套接字 -- bind四、数据的发送和接收 -- `sendto…...
缓存替换算法与存储器管理的分页、分段、段页式管理联系
缓存替换算法与存储器管理的分页、分段、段页式管理在目标和机制上存在相似性,均涉及高效资源分配和地址映射,但应用层级和具体场景不同。以下是它们的联系与区别分析: 1. 核心联系:资源管理的共性 替换策略的必要性 无论是缓存&a…...
AI大模型基础设施:NVIDIA GPU和AMD MI300系列的区别
本文将从架构设计、性能、内存、功耗、软件生态、价格与性价比、供应链与市场表现等多个维度对比英伟达的GPU(以H100为代表)和AMD的Instinct MI300系列处理器(以MI300X GPU和MI300A APU为主)。以下是详细分析: 1. 架构…...
基于Matlab实现耦合模理论仿真程序
耦合模理论(Coupled Mode Theory,简称CMT)是一种广泛应用于光子学、微波工程和电子学领域的理论框架,用于分析和理解多模系统的相互作用。 耦合模理论主要研究两个或多个模式之间的能量交换,这些模式可以是电磁波、声…...
图片文件转base64存储在数据库
以下是将文件转换为Base64编码字符串的Java代码: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Base64;public class ImageToBase64 {/*** 将图片文件转换为Base64字符串* param filePath 图片文件路径* r…...
我的世界云端服务器具体是指什么?
我的世界云端服务器是指一种基于互联网的多人游戏服务器,将游戏服务器运行在云平台上,而不是在本地计算机中,这使用户不需要考虑自身电脑的性能和网络稳定性,只需要通过网络连接到云端服务器,就可以享受到顺畅的游戏体…...
shell脚本实现远程重启多个服务器
直接deepseek帮写脚本 remoteReboot.sh #!/bin/bash # 配置文件路径(格式:每行一个服务器地址) SERVER_FILE"servers.list" # 读取服务器列表 mapfile -t SERVERS < "$SERVER_FILE" for server in "${SERVER…...
怎样快速变换 json 串里的多层集合
有一个 2 层的 json 串,下层是多个动态的 key-value,不含集合 / 数组类型。 {"Games": {"key1": "value1", "key2": value2,"key3":value3}} 现在要把下层变换成多层的集合。 {"Games":…...
FreeCAD傻瓜教程-涡轮蜗杆的快速绘制FCGear工作台的使用方法
起因:涡轮蜗轴的组合,是一种比较简单且高效的传动结构。可以实现减速、加速、转动角度的放大、缩小等应用。 如何绘制呢?我搜索了不少教程,看起来都挺复杂的,对于小白来说有点像天书。这里介绍和记录一下利用FreeCAD 的…...
【论文阅读】HunyuanVideo: A Systematic Framework For Large Video Generative Models
HunyuanVideo: A Systematic Framework For Large Video Generative Models 原文摘要 研究背景与问题 视频生成的变革性影响:近期视频生成技术的进步深刻改变了个人生活与行业应用。 闭源模型的垄断:主流视频生成模型(如Runway Gen-3、Luma …...
Search After+PIT 解决ES深度分页问题
1.深分页和search after 原理 深分页 (from/size)search_after数据定位全局排序后跳过前 N 条基于上一页最后一条的排序值定位排序开销每次请求重新全局排序 (O(N))仅首次全局排序,后续游标跳转 (O(1))内存消耗堆内存存储完整结果集 (高风险OOM)无堆内存累积 (安全…...
c语法高阶—(联合体,枚举,位域,编译器,宏定义,条件编译,条件编译,头文件)
目录 一 联合体(重要) 特性 总结 二 枚举(重要) 特性 总结: 三 位域(了解) 定义 特性 使用场景 优缺点分析表 位域的特点和使用方法 总结: 四 编译器(linux…...
SQL Server To Paimon Demo by Flink standalone cluster mode
需求:使用 Flink CDC 测试 SQL Server 连接 Paimon 操作:启动 Flink standalone cluster 后,接着启动 Flink SQL Client,则通过 Flink SQL Client 提交 insert & select job 到该 8081 cluster Flink SQL Client 执行案例 -…...
常用设计模式在 Spring Boot 项目中的实战案例
引言 在当今的软件开发领域,Spring Boot 以其高效、便捷的特性成为构建 Java 应用程序的热门框架。而设计模式作为软件开发中的宝贵经验总结,能够显著提升代码的可维护性、可扩展性和可复用性。本文将深入探讨几种常用设计模式在 Spring Boot 项目中的…...
4、反应釜压力监控系统 - /自动化与控制组件/reaction-vessel-monitor
76个工业组件库示例汇总 反应釜压力监控组件 这是一个用于反应釜压力监控的自定义组件,专为化工厂反应釜压力监控设计。采用苹果工业风格界面,简洁优雅,功能实用,易于使用。 功能特点 实时压力可视化:直观展示反应…...
五、Hadoop集群部署:从零搭建三节点Hadoop环境(保姆级教程)
作者:IvanCodes 日期:2025年5月7日 专栏:Hadoop教程 前言: 想玩转大数据,Hadoop集群是绕不开的一道坎。很多小伙伴一看到集群部署就头大,各种配置、各种坑。别慌!这篇教程就是你的“救生圈”。 …...
详细剖析传输层协议(TCP和UDP)
详细讲解传输层的网络协议,为什么TCP是可靠连接协议,凭什么能做到不丢包,有哪些机制保证可靠呢? TCP/UDP UDPTCP**三次握手和四次挥手****滑动窗口****拥塞控制**(socket套接字)**listen的第二个参数** UD…...
ZYNQ移植FreeRTOS与OpenAMP双核开发实践指南
ZYNQ系列芯片凭借其“ARM处理器(PS)+ FPGA(PL)”的异构架构,在嵌入式系统中被广泛应用于高性能计算与实时控制场景。然而,如何高效利用其双核资源并实现实时操作系统(如FreeRTOS)的移植与双核通信,是开发者面临的关键挑战。本文将深入探讨FreeRTOS移植、双核固化启动以…...
VUE+ElementUI 使用el-input类型type=“number” 时,取消右边的上下箭头
项目场景: 提示:这里简述项目相关背景: 在项目中有时候需要输入框的type“number”,这个时候,输入框的右边就会出现两个按钮,这两个按钮可以递增/递减,但是这样输入框看上去就不太美观&#x…...
RabbitMQ高级特性
1.消息的可靠投递 在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。 1.confirm 确认模式 2.return 退回模式 rabbitmq 整个消息投递的路径为: producer…...
在Python中调用C/C++函数并与MPI集成
在Python中调用C/C函数并与MPI集成 要在Python环境中调用C/C函数并让Python和C/C端都能使用MPI进行通信,有几种方法可以实现。下面我将介绍几种常见的方法。 方法一:使用mpi4py C/C MPI扩展 1. 准备工作 首先确保你已安装: MPI实现 (如OpenMPI或MP…...
软件架构评估方法全面解析
介绍 在软件开发过程中,架构设计的好坏直接影响系统的可维护性、可扩展性和性能。因此,软件架构评估(Software Architecture Evaluation)成为确保架构质量的关键步骤。本文将介绍几种主流的架构评估方法,包括ATAM、SA…...
场景可视化与数据编辑器:构建数据应用情境
场景可视化是将数据与特定的应用场景相结合,借助数据编辑器对数据进行灵活处理和调整,通过模拟和展示真实场景,使企业能够更直观地理解数据在实际业务中的应用和影响,为企业的决策和运营提供有力支持。它能够将抽象的数据转化为具…...
MATLAB导出和导入Excel文件表格数据并处理
20250507 1.MATLAB使用table函数和writetable函数将数据导出Excel表格文件 我们以高斯函数为例子,高斯函数在数学和工程领域有着广泛的应用,它的一般形式为: 其中是均值,决定了函数的中心位置; 是标准差,决…...
2025年渗透测试面试题总结-渗透岗位全职工作面试(附回答)(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 一、通用基础类问题 1. 自我介绍 2. 职业动机与规划 3. 加班/出差接受度 二、安全技术类问题 1. 漏…...
【django.db.utils.OperationalError: unable to open database file】
解决platform.sh 环境下,无法打开数据库问题 场景 在platform.sh 执行python manage.py createsuperuser是提示 django.db.utils.OperationalError: unable to open database file 错误 原因 由于settings.py文件中 本地数据库配置在线上配置后,导致…...
【人工智能】解锁AI潜能:LM Studio多模型并行运行DeepSeek与开源大模型的实践指南
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着大语言模型(LLM)的快速发展,LM Studio作为一款本地化部署工具,以其简单易用的图形化界面和强大的模型管理能力受到广泛关注。本文深…...
集群免密登录
免密登录原理 核心步骤 在hadoop100上 生成密钥对。把hadoop100的公钥发到hadoop101上。在hadoop100上登录hadoop101,验证效果 具体操作 登录 hadoop100。使用finalshell连接。在hadoop100上,运行命令:ssh-keygen -t rsa。然后根据提示连续敲…...
【C/C++】errno/strerror 和 GetLastError()/FormatMessage 的区别
strerror 和 errno 详解 printf("Error: %s\n", strerror(errno));这行代码用于在 C 语言中输出系统错误信息,但它与 Windows 的 GetLastError() 有重要区别。下面我将详细解释每个部分及其工作原理。 1. 组件解析 errno 定义:errno 是一个…...
ASP.NET MVC4 技术单选及多选题目汇编
一、单选题(共50题,每题2分) 1、ASP.NET MVC4 的核心架构模式是什么? A. MVP B. MVVM C. MVC D.三层架构 答案:C 2、在 MVC4 中,默认的路由配置文件名是? A. Global.asax B. RouteConfig.cs C.…...
趣味编程:梦幻万花筒
目录 1.效果展示 2.源码展示 3.代码逻辑详解 3.1 头文件与宏定义 3.2 HSV函数转RGB颜色函数 3.3 主函数 初始化部分 循环部分 线条绘制部分 刷新和延时部分 结束部分 4.小结 本篇博客主要介绍趣味编程用C语言实现万花筒小程序。 1.效果展示 2.源码展示 #define…...
使用 Selenium 截图功能,截不到原生 JavaScript 弹窗
本篇内容源自ai注意甄别 Selenium WebDriver 的标准截图 (getScreeenshotAs) 捕获的是浏览器渲染的 DOM 内容,而 JavaScript 的 alert()、confirm()、prompt() 这类弹窗是浏览器级别的原生 UI 元素,它们不属于页面的 DOM 结构。 为什么会这样ÿ…...
dubbo-token验证
服务提供者过滤器 import java.util.Map; import java.util.Objects;/*** title ProviderTokenFilter* description 服务提供者 token 验证* author zzw* version 1.0.0* create 2025/5/7 22:17**/ Activate(group CommonConstants.PROVIDER) public class ProviderTokenFilt…...
C++入门之认识整型
目录 一、变量 1.导入 2.变量 2.1 变量的作用 2.2 变量的定义方式 2.3 变量的“规矩” 二、数据类型 1.概念 2.int整型 三、C的常见运算 四、输入操作 4.1 cin 4.2 try 1 try 4.2.1 cin>> 4.2.2 定义的整数类型,输入字母会怎么样? …...
【数据结构入门训练DAY-28】蓝桥杯算法提高VIP-产生数
文章目录 前言一、题目二、解题思路结语 前言 本次训练内容 训练高精度乘法。训练解题思维。 一、题目 给出一个整数 n 和 k 个变换规则。规则:一位数可变换成另一个一位数:规则的右部不能为零。例如:n234。有规则(k&…...
学习笔记:黑马程序员JavaWeb开发教程(2025.3.29)
11.5 案例-文件上传-阿里云OSS-入门 出现报错:Process exited with an error: 1 (Exit value: 1),点击exec那一行,出现错误原因:Command execution failed. 在CSDN上找到了解决方法: 之后出现新的报错:Caug…...
大语言模型中的“温度”参数到底是什么?如何正确设置?
近年来,市面上涌现了大量调用大模型的工具,如 Dify、Cherry Studio 等开源或自研平台,几乎都提供了 “温度”(Temperature) 选项。然而,很多人在使用时并不清楚该如何选择合适的温度值。 今天,…...
【C++】C++中的类型转换
🚀write in front🚀 📜所属专栏: C学习 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大…...
Go语言基础学习详细笔记
文章目录 初步了解Go语言Go语言诞生的主要问题和目标Go语言应用典型代表Go语言开发环境搭建经典HelloWorld 基本程序结构编写学习变量常量数据类型运算符 条件语句if语句switch 语句 跳转语句常用集合和字符串数组切片Map实现Set**字符串** 函数**基本使用用例验证** 面向对象编…...
初始图形学(7)
上一章完成了相机类的实现,对之前所学的内容进行了封装与整理,现在要学习新的内容。 抗锯齿 我们放大之前渲染的图片,往往会发现我们渲染的图像边缘有尖锐的"阶梯"性质。这种阶梯状被称为"锯齿"。当真实的相机拍照时&a…...
Linux 安装交叉编译器后丢失 `<asm/errno.h>` 的问题及解决方案
前言 在 Linux (Ubuntu等)环境下安装某些软件或开发环境时,我们可能会意外地引入交叉编译工具链,尤其是用于 ARM 架构的交叉编译器,比如 gcc-arm-linux-gnueabi 等。而这种行为会修改系统原有的开发环境,甚至导致无法编译原生程序。本文记录一次在 Ubuntu 18.04 上编译 …...
无人机上的热成像相机可以单独使用吗?
想知道无人机上的热成像相机是否可以单独使用,这需要从多个方面来分析。首先,得理解热成像相机的工作原理和依赖条件。热成像本身需要传感器和处理器来捕捉和处理红外辐射,所以无人机是否必须作为载体呢? 无人机上的热成像相机是否…...
go基于redis+jwt进行用户认证和权限控制
go基于redisjwt进行用户认证和权限控制: 基于 jwt 实现用户认证 基于 redis 记录用户的角色和权限 效果 实现 用户认证 和 权限控制 核心实现 下面的例子:有三个用户,分别为三个角色:admin、user、manager 路由: …...
深入理解Java三大特性:封装、继承和多态
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
复刻低成本机械臂 SO-ARM100 上位机控制调试
视频讲解: 复刻低成本机械臂 SO-ARM100 上位机控制调试 SO-ARM100机械臂组装并且标定完成后,下一步就是整臂的调试,由于只做了follower这个从臂,所以要使用lerobot仓库中遥操作控制的方式就不行了,这里发现了bambot这个…...
代码随想录图论part4
图论part04 字符串接龙 代码随想录 该题本质是最短路径问题,方法:广搜 通过逐个修改字符完成从一点到另一点的变换 具体是通过对栈顶字符串的每个字符用26个字母逐个替换 每次替换要判断是否抵达终点 抵达终点返回结果 没有抵达终点就判断是否是已…...
台州智惠自动化签约智橙PLM,让创新持续发生
日前,台州智惠自动化科技有限公司(以下简称“智惠自动化”)正式签约了智橙PLM,本次签约是工业自动化领域的革新者和工业研发创新平台的“新新联合”,对“制造之都”台州的制造业转型有着重要意义和深远影响。 智惠自动…...
南京大学OpenHarmony技术俱乐部正式揭牌 仓颉编程语言引领生态创新
2025年4月24日,由OpenAtom OpenHarmony(以下简称“OpenHarmony”)项目群技术指导委员会与南京大学软件学院共同举办的“南京大学OpenHarmony技术俱乐部成立大会暨基础软件与生态应用论坛”在南京大学仙林校区召开。 大会聚焦国产自主编程语言…...
实现一个漂亮的Three.js 扫光地面 圆形贴图扫光
实现一个漂亮的Three.js 扫光地面 圆形贴图扫光 https://threehub.cn/#/codeMirror?navigationThreeJS&classifyshader&idcircleWave import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js import { GUI } fr…...
第16章 Python数据类型详解:列表(List)与运维开发实践
文章目录 第16章 Python数据类型详解:列表(List)与运维开发实践一、列表的基础和入门1. 基本操作2. 常用方法3. 列表推导式(List Comprehension)二、AIOps运维视角下的列表应用1. 日志分析与异常检测2. 时间序列数据处理3. 自动化决策与响应三、DevOps运维开发视角下的列表…...