Linux UDP 编程详解
一、引言
在网络编程领域,UDP(User Datagram Protocol,用户数据报协议)作为一种轻量级的传输层协议,具有独特的优势和适用场景。与 TCP(Transmission Control Protocol,传输控制协议)相比,UDP 不提供可靠的连接保证、数据顺序传递以及流量控制等功能,但它具有更低的开销和更高的传输效率,适用于对实时性要求较高、能容忍少量数据丢失的应用场景,如视频流传输、音频广播、在线游戏等。在 Linux 系统中,提供了丰富的函数库和工具来支持 UDP 编程,使得开发者能够轻松构建基于 UDP 的网络应用。本文将深入探讨 Linux 环境下的 UDP 编程,从基本概念、原理到详细的代码示例,帮助读者全面掌握 UDP 编程技术。
二、UDP 协议基础
2.1 UDP 协议特点
- 无连接性:UDP 在发送数据之前不需要像 TCP 那样建立连接,发送方可以直接将数据报发送给目标地址,接收方随时准备接收数据。这种特性使得 UDP 的传输过程更加简单、快捷,减少了建立连接所需的时间和资源开销。
- 不可靠性:UDP 不保证数据报一定能够正确、完整地到达接收方,也不保证数据报的顺序。在网络传输过程中,数据报可能会因为网络拥塞、链路故障等原因丢失或乱序。应用程序需要根据自身的需求来处理这些可能出现的问题,例如通过校验和、重传机制等方式来确保数据的完整性和正确性。
- 面向数据报:UDP 以数据报为单位进行数据传输,每个数据报都是独立的,包含了目标地址、源地址和数据等信息。发送方每次调用发送函数(如
sendto)发送的数据都会被封装成一个独立的数据报,接收方通过接收函数(如recvfrom)接收一个个独立的数据报。 - 头部开销小:UDP 的头部固定为 8 字节,相比 TCP 的 20 字节(不包含选项)头部开销更小,这使得 UDP 在传输大量小数据时具有更高的效率。UDP 头部包含源端口号、目的端口号、长度和校验和字段。
2.2 UDP 应用场景
- 实时多媒体传输:如视频会议、在线直播、网络电话等应用对实时性要求极高,少量的数据丢失可能只会导致短暂的画面卡顿或声音不清晰,但不会对整体的用户体验造成严重影响。使用 UDP 可以避免 TCP 的重传机制带来的延迟,保证媒体流的流畅传输。
- 网络监控与管理:在网络监控系统中,需要实时收集网络设备的状态信息、流量数据等。由于监控数据通常量较大且对实时性要求较高,使用 UDP 可以快速地将数据发送到监控中心,即使部分数据丢失也不会影响对网络整体状态的判断。
- 在线游戏:游戏中的实时状态更新、玩家操作指令等数据需要及时传输给服务器和其他玩家。UDP 的低延迟特性使得游戏能够更及时地响应用户操作,提供流畅的游戏体验。例如,在多人在线射击游戏中,玩家的移动、射击等操作需要快速传输到服务器,UDP 能够满足这种实时性需求。
三、Linux UDP 编程基础函数
3.1 socket 函数
socket函数用于创建一个套接字描述符,它是进行网络通信的基础。其函数原型如下:
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain参数指定协议族,对于 IPv4 网络,通常使用AF_INET;对于 IPv6 网络,使用AF_INET6。type参数指定套接字类型,UDP 编程使用SOCK_DGRAM,表示数据报套接字。protocol参数通常设置为 0,让系统根据domain和type选择默认的协议。对于 UDP,默认协议为 UDP 协议。
函数成功时返回一个非负整数的套接字描述符,失败时返回 -1,并设置errno错误码以指示错误原因。例如
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);
}
3.2 bind 函数
bind函数用于将套接字绑定到一个特定的地址和端口上。其函数原型如下:
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd是通过socket函数创建的套接字描述符。addr是一个指向struct sockaddr结构体的指针,该结构体包含了要绑定的地址信息。在 IPv4 中,通常使用struct sockaddr_in结构体来填充地址信息,然后将其强制转换为struct sockaddr类型。addrlen参数指定addr结构体的长度。
对于 IPv4,struct sockaddr_in结构体的定义如下:
struct sockaddr_in {sa_family_t sin_family; /* 地址族,AF_INET */in_port_t sin_port; /* 端口号 */struct in_addr sin_addr; /* 32位IPv4地址 */char sin_zero[8]; /* 填充字节,使其与struct sockaddr大小相同 */
};
struct in_addr {in_addr_t s_addr; /* 32位IPv4地址 */
};
在使用bind函数时,需要正确填充struct sockaddr_in结构体的各个字段。例如:
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8080); // 绑定到8080端口,htons用于将主机字节序转换为网络字节序
servaddr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有可用的网络接口if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);
}
3.3 sendto 函数
sendto函数用于向指定的目标地址发送数据报。其函数原型如下:
#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_DONTROUTE 表示不查找路由表。dest_addr是一个指向目标地址结构体的指针,指定数据报的接收方地址。addrlen参数指定目标地址结构体的长度。
函数成功时返回实际发送的字节数,失败时返回 -1,并设置errno错误码。例如:
char buffer[] = "Hello, UDP!";
struct sockaddr_in cliaddr;
memset(&cliaddr, 0, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(9090);
inet_pton(AF_INET, "192.168.1.100", &cliaddr.sin_addr); // 设置目标IP地址ssize_t n = sendto(sockfd, buffer, sizeof(buffer) - 1, 0,(struct sockaddr *)&cliaddr, sizeof(cliaddr));
if (n == -1) {perror("sendto failed");
}
3.4 recvfrom 函数
recvfrom函数用于从套接字接收数据报,并获取发送方的地址信息。其函数原型如下:
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
sockfd是接收数据的套接字描述符。buf是用于存储接收到数据的缓冲区。len是缓冲区的长度,以字节为单位。flags参数通常设置为 0,用于指定一些额外的接收选项,如 MSG_PEEK 表示只是查看数据而不真正从接收队列中移除。src_addr是一个指向结构体的指针,用于存储发送方的地址信息。addrlen是一个指向size_t类型变量的指针,用于指定src_addr结构体的长度,函数返回时会更新该变量为实际接收到的地址长度。
函数成功时返回实际接收到的字节数,失败时返回 -1,并设置errno错误码。例如:
char buffer[1024];
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0,(struct sockaddr *)&cliaddr, &len);
if (n == -1) {perror("recvfrom failed");
} else {buffer[n] = '\0';printf("Received: %s\n", buffer);
}
四、Linux UDP 编程示例
4.1 UDP 服务器示例
下面是一个简单的 UDP 服务器示例代码,该服务器绑定到指定的端口,接收客户端发送的数据,并将接收到的数据回显给客户端。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define BUFFER_SIZE 1024void usage(const char *prog_name) {printf("Usage: %s <listen_ip> <listen_port>\n", prog_name);printf("Example: %s 127.0.0.1 8080\n", prog_name);exit(EXIT_FAILURE);
}int main(int argc, char *argv[]) {int sockfd;struct sockaddr_in servaddr, cliaddr;socklen_t len;char buffer[BUFFER_SIZE];ssize_t n;// 检查命令行参数数量是否正确if (argc!= 3) {usage(argv[0]);}// 创建 UDP 套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);}// 初始化服务器地址结构体memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(atoi(argv[2]));if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {perror("Invalid IP address");close(sockfd);exit(EXIT_FAILURE);}// 绑定套接字到服务器地址if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}printf("UDP server is listening on %s:%d...\n", argv[1], atoi(argv[2]));while (1) {// 接收客户端数据len = sizeof(cliaddr);n = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0,(struct sockaddr *)&cliaddr, &len);if (n == -1) {perror("recvfrom failed");continue;}buffer[n] = '\0';printf("Received from client (%s:%d): %s\n",inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), buffer);// 将接收到的数据回显给客户端n = sendto(sockfd, buffer, strlen(buffer), 0,(struct sockaddr *)&cliaddr, len);if (n == -1) {perror("sendto failed");}}close(sockfd);return 0;
}
在这个示例中,服务器首先创建一个 UDP 套接字,然后将其绑定到指定的端口。通过一个无限循环,服务器不断调用recvfrom函数接收客户端发送的数据,并在接收到数据后调用sendto函数将数据回显给客户端。
4.2 UDP 客户端示例
以下是与上述服务器对应的 UDP 客户端示例代码,客户端向服务器发送数据,并接收服务器回显的数据。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define BUFFER_SIZE 1024void usage(const char *prog_name) {printf("Usage: %s <server_ip> <port> <message>\n", prog_name);printf("Example: %s 127.0.0.1 8080 \"Hello, server!\"\n", prog_name);exit(EXIT_FAILURE);
}int main(int argc, char *argv[]) {int sockfd;struct sockaddr_in servaddr;char buffer[BUFFER_SIZE];ssize_t n;socklen_t len;// 检查命令行参数数量是否正确if (argc!= 4) {usage(argv[0]);}// 创建 UDP 套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);}// 初始化服务器地址结构体memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(atoi(argv[2]));if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {perror("Invalid IP address");close(sockfd);exit(EXIT_FAILURE);}// 向服务器发送数据n = sendto(sockfd, argv[3], strlen(argv[3]), 0,(struct sockaddr *)&servaddr, sizeof(servaddr));if (n == -1) {perror("sendto failed");close(sockfd);exit(EXIT_FAILURE);}printf("Sent %ld bytes to server: %s\n", n, argv[3]);// 接收服务器回显的数据len = sizeof(servaddr);n = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0,(struct sockaddr *)&servaddr, &len);if (n == -1) {perror("recvfrom failed");close(sockfd);exit(EXIT_FAILURE);}buffer[n] = '\0';printf("Received from server: %s\n", buffer);close(sockfd);return 0;
}
客户端同样先创建一个 UDP 套接字,然后初始化服务器的地址信息。通过sendto函数向服务器发送数据,接着使用recvfrom函数接收服务器回显的数据。
代码解释
- 服务器端代码:
socket(AF_INET, SOCK_DGRAM, 0):创建一个 UDP 套接字。AF_INET表示使用 IPv4 地址族,SOCK_DGRAM表示使用数据报套接字类型,0表示使用默认协议(对于AF_INET和SOCK_DGRAM组合,即为 UDP 协议)。memset(&servaddr, 0, sizeof(servaddr)):将servaddr结构体的内存清零,确保其成员变量初始化为零。servaddr.sin_family = AF_INET:设置地址族为 IPv4。servaddr.sin_port = htons(PORT):将端口号转换为网络字节序并存储在sin_port中。servaddr.sin_addr.s_addr = INADDR_ANY:将套接字绑定到所有可用的网络接口。bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)):将套接字绑定到本地地址和端口,使得服务器可以接收发送到该端口的数据。recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr *)&cliaddr, &len):从客户端接收数据,存储在buffer中,并将发送方的地址存储在cliaddr中。sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&cliaddr, len):将接收到的数据发送回客户端。
- 客户端代码解释:
socket(AF_INET, SOCK_DGRAM, 0):创建一个 UDP 套接字,与服务器端相同。memset(&servaddr, 0, sizeof(servaddr)):将servaddr结构体的内存清零。servaddr.sin_family = AF_INET:设置地址族为 IPv4。servaddr.sin_port = htons(PORT):将端口号转换为网络字节序。inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr):将服务器的 IP 地址字符串转换为二进制格式存储在sin_addr中。sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)):向服务器发送数据。recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr *)&servaddr, &len):接收服务器回显的数据。
五、编译指令和测试过程
5.1 编译
gcc udp_server.c -o udp_server
gcc udp_client.c -o udp_client
5.2 测试过程
启动服务端 监听端口
./udp_server 127.0.0.1 8080
客户端发送数据
./udp_client 127.0.0.1 8080 helloworld123

六、UDP 编程中的常见问题与解决方案
6.1 数据丢失问题
由于 UDP 的不可靠性,数据在传输过程中可能会丢失。为了解决这个问题,可以在应用层实现数据校验和重传机制。例如,发送方在每个数据报中添加一个校验和字段,接收方在接收到数据报后计算校验和并与发送方发送的校验和进行比较,如果不一致则请求发送方重传该数据报。另外,可以设置一个重传定时器,当发送方在一定时间内未收到接收方的确认消息时,自动重传数据报。
6.2 数据报大小限制
UDP 数据报的大小受到网络 MTU(Maximum Transmission Unit,最大传输单元)的限制。在 IPv4 网络中,MTU 通常为 1500 字节(不包括链路层头部),UDP 数据报的总长度(包括头部)不能超过 MTU。如果需要发送的数据超过 MTU 大小,需要将数据进行拆分,分成多个较小的数据报进行发送。接收方在接收到多个数据报后,需要按照正确的顺序进行重组。
6.3 网络拥塞问题
虽然 UDP 没有像 TCP 那样的拥塞控制机制,但在网络拥塞严重的情况下,大量的数据报可能会被丢弃。为了减轻网络拥塞对 UDP 应用的影响,可以在应用层实现一些简单的拥塞控制策略,如根据网络状况动态调整发送数据的速率。例如,当发现丢包率增加时,适当降低发送速率;当网络状况良好时,逐渐提高发送速率。
6.4 可能遇到的问题及解决方法
- 权限问题:如果在运行时遇到权限问题,可能是因为使用了低端口号(小于 1024),可以使用
sudo命令来运行可执行文件,或者将端口号修改为大于 1024 的端口。 - 地址冲突:如果服务器绑定的端口已被其他程序占用,会导致绑定失败,可以修改服务器的端口号。
相关文章:
Linux UDP 编程详解
一、引言 在网络编程领域,UDP(User Datagram Protocol,用户数据报协议)作为一种轻量级的传输层协议,具有独特的优势和适用场景。与 TCP(Transmission Control Protocol,传输控制协议࿰…...
【2024年华为OD机试】(B卷,100分)- 计算最接近的数 (Java JS PythonC/C++)
一、问题描述 题目解析 我们需要找到一个下标 i,使得表达式 X[i] - X[i 1] - ... - X[i K - 1] 的结果最接近于数组的中位数。如果有多个 i 满足条件,则返回最大的 i。 关键点: 中位数计算: 将数组排序后,中位数…...
Pytorch 自学笔记(三):利用自定义文本数据集构建Dataset和DataLoader
Pytorch 自学笔记(三) 1. Dataset与DataLoader1.1 torch.utils.data.Dataset1.2 torch.utils.data.DataLoader Pytorch 自学笔记系列的第三篇。针对Pytorch的Dataset和DataLoader进行简单的介绍,同时,介绍如何使用自定义文本数据集…...
QT 使用QSqlTableModel对数据库进行创建,插入,显示
文章目录 效果图概述功能点代码分析初始数据插入数据数据显示 总结 效果图 概述 本案例用于对数据库中的数据进行显示等其他操作,其他表格筛选,过滤等功能可看此博客 框架:数据模型使用QSqlTableModel,视图使用QTableView&#x…...
如何学习Transformer架构
Transformer架构自提出以来,在自然语言处理领域引发了革命性的变化。作为一种基于注意力机制的模型,Transformer解决了传统序列模型在并行化和长距离依赖方面的局限性。本文将探讨Transformer论文《Attention is All You Need》与Hugging Face Transform…...
浅谈云计算22 | Kubernetes容器编排引擎
Kubernetes容器编排引擎 一、Kubernetes管理对象1.1 Kubernetes组件和架构1.2 主要管理对象类型 二、Kubernetes 服务2.1 服务的作用与原理2.2 服务类型 三、Kubernetes网络管理3.1 网络模型与目标3.2 网络组件3.2.1 kube-proxy3.2.2 网络插件 3.3 网络通信流程 四、Kubernetes…...
计算 SAMOut V3 在将词汇表从1万 增加到6千万的情况下能够减少多少参数
当我们将词汇表从 60,000,000(六千万)减少到 10,000 时,实际上是在缩小模型的词嵌入层及其共享的语言模型头(LM Head)的规模。这将导致参数量显著减少。我们可以通过以下步骤来计算具体的参数减少量。 参数量减少计算…...
03.选择排序
一、题目思路 选择排序是一种简单直观的排序算法。它的工作原理是:首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大ÿ…...
02_登录窗口
新建场景 重命名为GameRoot 双击GameRoot进入新场景 同样摄像机清除格式 删除平行光并关闭渲染灯光的天空盒 新建空节点重命名为GameRoot GameRoot为游戏的根节点 在整个游戏中都不会被删除 在游戏的根节点下创建UI的根节点Canvas 创建一个空节点 作为UI根节点下的 登录场景UI…...
NodeJS | 搭建本地/公网服务器 live-server 的使用与安装
目录 介绍 安装 live-server 安装方法 安装后的验证 环境变量问题 Node.js 环境变量未配置正确 全局安装的 live-server 路径未添加到环境变量 运行测试 默认访问主界面 访问文件 报错信息与解决 问题一:未知命令 问题二:拒绝脚本 公网配置…...
SystemUI 实现音量条同步功能
需求:SystemUI 实现音量条同步功能 具体问题 以前在SystemUI 下拉框添加了音量条控制,目前发现在SystemUI下拉框显示状态的情况下, 按键或者底部虚拟导航点击音量加减时候,SystemUI音量条不更新。 如下图:两个Syste…...
嵌入式知识点总结 C/C++ 专题提升(一)-关键字
针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。 目录 1.C语言宏中"#“和"##"的用法 1.1.(#)字符串化操作符 1.2.(##)符号连接操作符 2.关键字volatile有什么含意?并举出三个不同的例子? 2.1.并行设备的硬件寄存…...
基础入门-传输加密数据格式编码算法密文存储代码混淆逆向保护安全影响
知识点: 1、传输格式&传输数据-类型&编码&算法 2、密码存储&代码混淆-不可逆&非对称性 一、演示案例-传输格式&传输数据-类型&编码&算法 传输格式 JSON XML WebSockets HTML 二进制 自定义 WebSockets:聊天交互较常…...
几个Linux系统安装体验(续): 统信桌面系统
本文介绍统信桌面系统(uos)的安装。 下载 下载地址: https://www.chinauos.com/resource/download-professional 下载文件:本文下载文件名称为uos-desktop-20-professional-1070-amd64.iso。 下载注意事项:可直接下…...
算法日记6.StarryCoding P52:我们都需要0(异或)
一、题目 二、题解: 1、对于这道题,题意为让我们寻找一个数x使得 b[i]a[i]^x, 并且b[1]^b[2]^b[3]^ b[4]^b[5]....0 2、我们把b[i]给拆开,可以得到 3、又因为^满足结合律,因此,可以把括号给拆开 4、接着…...
【网络协议】RFC3164-The BSD syslog Protocol
引言 Syslog常被称为系统日志或系统记录,是一种标准化的协议,用于网络设备、服务器和应用程序向中央Syslog服务器发送日志消息。互联网工程任务组(IETF)发布的RFC 3164,专门定义了BSD Syslog协议的规范和实现方式。通…...
SpringCloud -根据服务名获取服务运行实例并进行负载均衡
Nacos注册中心 每个服务启动之后都要向注册中心发送服务注册请求,注册中心可以和各个注册客户端自定义协议实现服务注册和发现。 pom.xml <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-na…...
CentOS 安装Redis
1. 安装 Redis 安装 EPEL 仓库(对于 CentOS/RHEL 系统): 首先安装 EPEL 仓库,因为 Redis 存在于 EPEL 仓库中: yum install epel-release安装 Redis 数据库: yum install redis2. 修改 Redis 配置文件 …...
Linux网络 TCP socket
TCP简介 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它位于OSI模型的第四层,主要为应用层提供数据传输服务。TCP通过三次握手建立连接,确保数据在发送和接收过程中的准确性和顺序…...
(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)
一、四大坐标系介绍 1,世界坐标系 从这个世界(world)的视角来看物体 世界坐标系是3D空间坐标,每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)表示 2,相机坐标系 相机本身具有一个坐标系&…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
