UDP 单播、多播、广播:原理、实践
一、引言
在计算机网络通信领域,UDP(User Datagram Protocol,用户数据报协议)是一种重要的传输层协议。它以无连接、低开销的特点,在众多实时性要求高的应用场景中发挥关键作用。UDP 支持单播、多播和广播三种通信模式,每种模式都有其独特的应用场景和工作原理。深入理解这些通信模式,对于开发高效的网络应用程序至关重要。
二、UDP 基础概述
UDP 是一种无连接的传输层协议,它在网络层 IP 协议的基础上,为应用层提供了简单的数据传输服务。与面向连接的 TCP(Transmission Control Protocol)协议不同,UDP 不保证数据的可靠传输、顺序交付以及数据的完整性。然而,UDP 的这些特性使得它在一些对实时性要求较高,对数据准确性要求相对较低的场景中具有显著优势,如实时音频和视频流、在线游戏、网络管理等。
UDP 数据报由首部和数据两部分组成。首部长度固定为 8 字节,包含四个字段:
- 源端口号(16 位):标识发送端应用程序的端口,用于接收端回发数据。
- 目的端口号(16 位):标识接收端应用程序的端口,用于确定数据的接收方。
- 长度(16 位):UDP 数据报的总长度,包括首部和数据部分,最小值为 8 字节(仅首部)。
- 校验和(16 位):用于检测数据报在传输过程中是否发生错误,但校验和是可选的,若不使用则该字段设为全零。
三、UDP 单播
3.1 概念描述
UDP 单播是一种一对一的通信方式,发送端向特定的一个接收端发送数据。在这种通信模式下,发送端在 UDP 数据报的首部中明确指定接收端的 IP 地址和端口号。网络设备根据数据报中的目的 IP 地址,通过路由算法将数据报转发到目标接收端。单播通信的特点是数据传输的针对性强,只有目标接收端能够接收到数据,适用于大多数需要精确通信的场景,如客户端 - 服务器模型的应用程序。
3.2 示例代码实现
3.2.1 发送端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(buffer, 0, sizeof(buffer));// 设置服务器地址servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT);servaddr.sin_addr.s_addr = inet_addr(SERVER_IP);char *msg = "Hello, Server!";sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *)&servaddr, sizeof(servaddr));printf("Message sent to server: %s\n", msg);close(sockfd);return 0;
}
3.2.2 接收端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr, cliaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(&cliaddr, 0, sizeof(cliaddr));// 设置服务器地址servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = INADDR_ANY;servaddr.sin_port = htons(PORT);// 绑定套接字到地址if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}socklen_t len = sizeof(cliaddr);int n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);buffer[n] = '\0';printf("Message received from client: %s\n", buffer);close(sockfd);return 0;
}
3.3 编译和测试过程
-
编译
- 在终端中,切换到包含
udp_unicast_sender.c
和udp_unicast_receiver.c
文件的目录。 - 编译发送端代码:
gcc -o udp_unicast_sender udp_unicast_sender.c
- 编译接收端代码:
gcc -o udp_unicast_receiver udp_unicast_receiver.c
- 在终端中,切换到包含
-
测试
- 首先在一个终端中运行接收端程序:
./udp_unicast_receiver
- 然后在另一个终端中运行发送端程序:
./udp_unicast_sender
- 接收端将显示接收到的消息:
Message received from client: Hello, Server!
- 首先在一个终端中运行接收端程序:
四、UDP 广播
4.1 概念描述
UDP 广播是一种一对所有的通信方式,发送端向网络中的所有设备发送数据。广播地址分为两种类型:有限广播和直接广播。
- 有限广播:使用地址 255.255.255.255,它是一种受限的广播地址,仅在本地网络内进行广播,路由器不会转发以有限广播地址为目的地址的数据包。
- 直接广播:网络地址的主机位全为 1 的地址。例如,对于网络 192.168.1.0/24,其直接广播地址为 192.168.1.255。直接广播数据包可以被路由器转发到指定网络的所有主机。
4.2 原理
4.2.1 有限广播原理
-
发送端
- 发送端创建 UDP 套接字,并设置套接字选项以允许广播(
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable))
),其中broadcastEnable
为一个非零值,通常设为 1。 - 构造 UDP 数据报,将目的 IP 地址设置为 255.255.255.255,目的端口号设置为接收端监听的端口号。
- 使用
sendto
函数发送数据报,数据报将在本地网络内广播,所有监听该端口的设备都能接收。
- 发送端创建 UDP 套接字,并设置套接字选项以允许广播(
-
接收端
- 接收端创建 UDP 套接字,并绑定到指定的端口号。
- 使用
recvfrom
函数接收数据报,当有广播数据到达时,接收端就能接收到。
4.2.2 直接广播原理
-
发送端
- 同样,发送端先创建 UDP 套接字并设置允许广播选项。
- 构造 UDP 数据报时,将目的 IP 地址设置为目标网络的直接广播地址,目的端口号设置为接收端监听的端口号。
- 使用
sendto
函数发送数据报,路由器会将该数据报转发到目标网络的所有主机。
-
接收端
- 接收端在目标网络内,创建 UDP 套接字并绑定到指定端口号。
- 使用
recvfrom
函数接收数据报,接收来自发送端的广播数据。
4.3 流程示意图
4.3.1 有限广播流程示意图
4.3.2 直接广播流程示意图
4.4 示例代码实现
4.4.1 有限广播发送端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define LIMITED_BROADCAST_IP "255.255.255.255"
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}int broadcastEnable = 1;// 设置套接字选项以允许广播if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) < 0) {perror("setsockopt failed");close(sockfd);exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(buffer, 0, sizeof(buffer));// 设置有限广播地址servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT);servaddr.sin_addr.s_addr = inet_addr(LIMITED_BROADCAST_IP);char *msg = "Hello, Local Network!";sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *)&servaddr, sizeof(servaddr));printf("Limited broadcast message sent: %s\n", msg);close(sockfd);return 0;
}
4.4.2 有限广播接收端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr, cliaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(&cliaddr, 0, sizeof(cliaddr));// 设置服务器地址servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = INADDR_ANY;servaddr.sin_port = htons(PORT);// 绑定套接字到地址if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}socklen_t len = sizeof(cliaddr);int n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);buffer[n] = '\0';printf("Limited broadcast message received: %s\n", buffer);close(sockfd);return 0;
}
4.4.3 直接广播发送端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define DIRECT_BROADCAST_IP "192.168.1.255"
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}int broadcastEnable = 1;// 设置套接字选项以允许广播if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) < 0) {perror("setsockopt failed");close(sockfd);exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(buffer, 0, sizeof(buffer));// 设置直接广播地址servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT);servaddr.sin_addr.s_addr = inet_addr(DIRECT_BROADCAST_IP);char *msg = "Hello, 192.168.1.0 Network!";sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *)&servaddr, sizeof(servaddr));printf("Direct broadcast message sent: %s\n", msg);close(sockfd);return 0;
}
4.4.4 直接广播接收端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr, cliaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(&cliaddr, 0, sizeof(cliaddr));// 设置服务器地址servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = INADDR_ANY;servaddr.sin_port = htons(PORT);// 绑定套接字到地址if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}socklen_t len = sizeof(cliaddr);int n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);buffer[n] = '\0';printf("Direct broadcast message received: %s\n", buffer);close(sockfd);return 0;
}
4.5 编译和测试过程
- 编译
- 有限广播
- 在终端中,切换到包含
udp_limited_broadcast_sender.c
和udp_limited_broadcast_receiver.c
文件的目录。 - 编译发送端代码:
gcc -o udp_limited_broadcast_sender udp_limited_broadcast_sender.c
- 编译接收端代码:
gcc -o udp_limited_broadcast_receiver udp_limited_broadcast_receiver.c
- 在终端中,切换到包含
- 直接广播
- 切换到包含
udp_direct_broadcast_sender.c
和udp_direct_broadcast_receiver.c
文件的目录。 - 编译发送端代码:
gcc -o udp_direct_broadcast_sender udp_direct_broadcast_sender.c
- 编译接收端代码:
gcc -o udp_direct_broadcast_receiver udp_direct_broadcast_receiver.c
- 切换到包含
- 有限广播
- 测试
- 有限广播
- 首先在本地网络内的多个终端中运行接收端程序:
./udp_limited_broadcast_receiver
- 然后在另一个终端中运行发送端程序:
./udp_limited_broadcast_sender
- 每个接收端都将显示接收到的有限广播消息:
Limited broadcast message received: Hello, Local Network!
- 首先在本地网络内的多个终端中运行接收端程序:
- 直接广播
- 在目标网络(192.168.1.0/24 为例)内的多个终端中运行接收端程序:
./udp_direct_broadcast_receiver
- 在可以向该目标网络发送直接广播的设备上运行发送端程序:
./udp_direct_broadcast_sender
- 目标网络内的每个接收端都将显示接收到的直接广播消息:
Direct broadcast message received: Hello, 192.168.1.0 Network!
- 在目标网络(192.168.1.0/24 为例)内的多个终端中运行接收端程序:
- 有限广播
五、UDP 多播
5.1 概念描述
UDP 多播(也称为组播)是一种一对多的通信方式,发送端向一组特定的接收端发送数据。这组接收端通过加入同一个多播组来接收数据。多播使用 D 类 IP 地址(范围是 224.0.0.0 到 239.255.255.255)来标识多播组。发送端将数据发送到多播组的 IP 地址,网络会将数据转发给组内的所有成员。多播适用于一些需要向特定的一组设备发送相同数据的场景,如在线视频会议、流媒体分发等。与广播不同,多播不会向网络中的所有设备发送数据,只有加入了相应多播组的设备才会接收数据,这样可以减少网络流量,提高传输效率。
5.2 原理
-
发送端
- 发送端创建 UDP 套接字。
- 构造 UDP 数据报时,将目的 IP 地址设置为多播组的 IP 地址,目的端口号设置为接收端监听的端口号。
- 使用
sendto
函数将数据报发送出去,网络会根据多播路由协议将数据转发到多播组的成员。发送端不需要关心组内成员的具体 IP 地址,只需要知道多播组的地址。
-
接收端
- 接收端创建 UDP 套接字,并绑定到指定的端口号。
- 为了加入多播组,接收端需要使用
setsockopt
函数设置套接字选项。具体来说,需要设置IP_ADD_MEMBERSHIP
选项,代码如下:
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);
mreq.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {perror("setsockopt failed");close(sockfd);exit(EXIT_FAILURE);
}
- 这里,
mreq
结构体包含多播组的 IP 地址和本地接口地址。通过设置IP_ADD_MEMBERSHIP
选项,接收端通知操作系统将该套接字加入指定的多播组。之后,接收端使用recvfrom
函数接收数据报,就能接收到发往该多播组的所有数据。
5.3 流程示意图
5.4 示例代码实现
5.4.1 多播发送端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define MULTICAST_IP "224.1.1.1"
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(buffer, 0, sizeof(buffer));// 设置多播地址servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT);servaddr.sin_addr.s_addr = inet_addr(MULTICAST_IP);char *msg = "Hello, Multicast Group!";sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *)&servaddr, sizeof(servaddr));printf("Multicast message sent: %s\n", msg);close(sockfd);return 0;
}
5.4.2 多播接收端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define MULTICAST_IP "224.1.1.1"
#define BUFFER_SIZE 1024int main(int argc, char const *argv[]) {int sockfd;struct sockaddr_in servaddr, cliaddr;struct ip_mreq mreq;char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}memset(&servaddr, 0, sizeof(servaddr));memset(&cliaddr, 0, sizeof(cliaddr));// 设置服务器地址servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = INADDR_ANY;servaddr.sin_port = htons(PORT);// 绑定套接字到地址if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}// 设置多播组地址和本地接口地址mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);mreq.imr_interface.s_addr = INADDR_ANY;// 加入多播组if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {perror("setsockopt failed");close(sockfd);exit(EXIT_FAILURE);}socklen_t len = sizeof(cliaddr);int n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);buffer[n] = '\0';printf("Multicast message received: %s\n", buffer);close(sockfd);return 0;
}
5.5 编译和测试过程
-
编译
- 在终端中,切换到包含
udp_multicast_sender.c
和udp_multicast_receiver.c
文件的目录。 - 编译发送端代码:
gcc -o udp_multicast_sender udp_multicast_sender.c
- 编译接收端代码:
gcc -o udp_multicast_receiver udp_multicast_receiver.c
- 在终端中,切换到包含
-
测试
- 首先在多个终端中运行接收端程序(模拟多播组成员):
./udp_multicast_receiver
- 然后在另一个终端中运行发送端程序:
./udp_multicast_sender
- 每个接收端都将显示接收到的多播消息:`Multicast message received: Hello, Multicast Group!
- 首先在多个终端中运行接收端程序(模拟多播组成员):
相关文章:
UDP 单播、多播、广播:原理、实践
一、引言 在计算机网络通信领域,UDP(User Datagram Protocol,用户数据报协议)是一种重要的传输层协议。它以无连接、低开销的特点,在众多实时性要求高的应用场景中发挥关键作用。UDP 支持单播、多播和广播三种通信模式…...
深入浅出:Go语言中的bytes包与字节串操作详解
标题:深入浅出:Go语言中的bytes包与字节串操作详解 引言 在Go语言的世界里,bytes包是一个非常重要的标准库,它为开发者提供了高效处理字节切片(byte slice)的功能。无论是处理二进制数据、UTF-8编码的字符串,还是进行高效的数据读写操作,bytes包都扮演着不可或缺的角色…...

数据库存储上下标符号,sqlserver 2008r2,dm8
sqlserver 2008r2: 数据类型需要用nvarchar插入数据时字符串前需要用N create table test( col1 varchar(50), col2 nvarchar(50) ) insert into test(col1,col2) values(U⁴⁵⁶⁷⁸⁹⁰D₁₂₃₄₅₆₇₈₉₀,U⁴⁵⁶⁷⁸⁹⁰D₁₂₃₄₅₆₇₈₉₀) insert into…...

LabVIEW串口通信调试与数据接收问题
在使用LabVIEW进行串口通信时,常常会遇到无法接收数据的情况。这可能与串口设置、连接、设备响应等多方面因素相关。本文将详细讨论如何使用LabVIEW进行串口通信,并提供常见问题的排查与解决方法,帮助用户更高效地进行数据接收调试。通过调整…...
oneplus3t-lineage-14编译-android7
lineageOS-14(android7)的开发者模式/usb调试(adb)有root功能, 而lineageOS-16(android9)无 oneplus3t-lineage-14编译-android7 1 清华linageos镜像 x lineage-14.1-20180223-nightly-oneplus3-signed.zip ntfs分区挂载为普通用户目录 , ext4分区挂载为普通用户目录 bfs…...

存储过程(SQL)
1.存储过程 存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。 2.MySQL存储过程创建…...

【I/O编程】UNIX文件基础
IO编程的本质是通过 API 操作 文件。 什么是 IO I - Input 输入O - Output 输出 这里的输入和输出都是站在应用(运行中的程序)的角度。外部特指文件。 这里的文件是泛指,并不是只表示存在存盘中的常规文件。还有设备、套接字、管道、链接…...

完美解决phpstudy安装后mysql无法启动
phpstudy数据库无法启动有以下几个原因。 **一、**自己在电脑上安装了MySQL数据库,MySQL的服务名为MySQL,这会与phpstudy的数据库的服务名发生冲突,从而造成phpstudy中的数据库无法启动,这时我们只需要将自己安装的MySQL的服务名改掉就行。 但是&#…...
自己造轮子-基于Ceres的GNSS-INS松耦合组合导航算法
之前硕士期间的研究课题涉及到GNSS-INS组合导航,入门看的武汉大学牛老师团队的KF-GINS,不得不说,大组的东西还是很棒的,很适合组合导航入门,KF-GINS主要是基于ESKF的GNSS/INS松耦合组合导航系统,博主就不在…...

「实战应用」如何为DHTMLX JavaScript 甘特图添加进度线
DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求,是最完善的甘特图图表库。 今天,您将学习如何使用进度线补充JavaScript 甘特图,以便于监控项目进度。 DHTMLX Gantt 最新试用版下载 …...
MySQL面试题2025 每日20道
1、MySQL 中的数据排序是怎么实现的? 简单 在 MySQL 中,数据排序是通过 ORDER BY 子句来实现的。当你执行一个查询语句时,可以在 SELECT 语句的末尾添加 ORDER BY 来指定按照哪个列进行排序,以及升序(ASC)…...

HTML学习笔记(4)
目录 一、背景相关样式 二、定位position 三、javascript 1、变量的定义 2、数据类型 3、绑定事件 一、背景相关样式 background-image: url(); // 背景图片 background-repeat: repeat; // 背景图片是否平铺 no-repeat background-size: 200px; // 背景图片尺寸 cover把…...
解决 MySQL 服务无法启动:failed to restart mysql.service unit not found
目录 前言1. 问题描述2. 问题分析3. 解决步骤 3.1 检查 MySQL 服务文件3.2 备份旧的服务文件3.3 启动 MySQL 服务3.4 验证服务状态 4. 总结结语 前言 在日常使用 MySQL 数据库时,有时候可能会遇到服务无法正常启动的问题。这类问题通常出现在系统更新或者服务配置…...
在 Ubuntu 上安装 Nginx 的详细指南
在Ubuntu系统中从源码安装Nginx可以让您自定义Nginx的编译选项和模块,以满足特定需求。以下是详细的步骤指南: 前提条件 更新系统包列表 sudo apt update sudo apt upgrade -y安装必要的依赖包 sudo apt install -y build-essential libpcre3 libpcre3-…...

58,【8】BUUCTF [PwnThyBytes 2019]Baby_SQL1
进入靶场 和2次注入的页面很像 不过养成查看源代码的好习惯 先访问source.zip 下载后解压,发现两个文件 第一个文件夹打开又有4个PHP文件 那还是先看index.php文件好了 有PHP和HTML两部分,下面是PHP部分代码(HTML太长了,先放一…...
2.1 三个世界”与“图灵测试”:人工智能与人类智能的深度探索
“三个世界”与“图灵测试”:人工智能与人类智能的深度探索 人工智能的研究和发展,尤其是对其认知能力和智能表现的探索,早在20世纪中期就已成为科学家的热议话题。随着技术的进步,学者们提出了许多思想框架来理解人工智能的运作及其与人类智能的关系。其中,“三个世界”…...

基于微信小程序的优购电商系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

JS宏进阶: 工厂函数与构造函数
一、构造函数 在JavaScript中,构造函数是一种用于创建和初始化对象的特殊函数。构造函数的名字通常以大写字母开头,以区分于普通函数。通过new关键字调用构造函数,可以创建一个新的实例对象,并自动执行构造函数内部的代码来初始化…...

【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚一、线程概念 📖 回顾进程 📖 引入线程 📖 总结 &a…...
关于ubuntu命令行连接github失败解决办法
如果发现ping github.com有问题 使用sudo gedit /ect/hosts 打开host文件 添加 140.82.114.4 github.com 发现使用git 克隆失败,出现 aliaubuntu:~/文档/ctest$ git clone https://github.com/LearningInfiniTensor/learning-cxx.git 正克隆到 ‘learning-cxx’… …...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...

从0开始学习R语言--Day17--Cox回归
Cox回归 在用医疗数据作分析时,最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据,往往会有很多的协变量,即使我们通过计算来减少指标对结果的影响,我们的数据中依然会有很多的协变量,且…...