UDP 单播、多播、广播:原理、实践

一、引言

在计算机网络通信领域,UDP(User Datagram Protocol,用户数据报协议)是一种重要的传输层协议。它以无连接、低开销的特点,在众多实时性要求高的应用场景中发挥关键作用。UDP 支持单播、多播和广播三种通信模式,每种模式都有其独特的应用场景和工作原理。深入理解这些通信模式,对于开发高效的网络应用程序至关重要。

二、UDP 基础概述

UDP 是一种无连接的传输层协议,它在网络层 IP 协议的基础上,为应用层提供了简单的数据传输服务。与面向连接的 TCP(Transmission Control Protocol)协议不同,UDP 不保证数据的可靠传输、顺序交付以及数据的完整性。然而,UDP 的这些特性使得它在一些对实时性要求较高,对数据准确性要求相对较低的场景中具有显著优势,如实时音频和视频流、在线游戏、网络管理等。

UDP 数据报由首部和数据两部分组成。首部长度固定为 8 字节,包含四个字段:

  1. 源端口号(16 位):标识发送端应用程序的端口,用于接收端回发数据。
  2. 目的端口号(16 位):标识接收端应用程序的端口,用于确定数据的接收方。
  3. 长度(16 位):UDP 数据报的总长度,包括首部和数据部分,最小值为 8 字节(仅首部)。
  4. 校验和(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 1024

int 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 1024

int 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 编译和测试过程

  1. 编译

    • 在终端中,切换到包含 udp_unicast_sender.cudp_unicast_receiver.c 文件的目录。
    • 编译发送端代码:gcc -o udp_unicast_sender udp_unicast_sender.c
    • 编译接收端代码:gcc -o udp_unicast_receiver udp_unicast_receiver.c
  2. 测试

    • 首先在一个终端中运行接收端程序:./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 有限广播原理
  1. 发送端

    • 发送端创建 UDP 套接字,并设置套接字选项以允许广播(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable))),其中 broadcastEnable 为一个非零值,通常设为 1。
    • 构造 UDP 数据报,将目的 IP 地址设置为 255.255.255.255,目的端口号设置为接收端监听的端口号。
    • 使用 sendto 函数发送数据报,数据报将在本地网络内广播,所有监听该端口的设备都能接收。
  2. 接收端

    • 接收端创建 UDP 套接字,并绑定到指定的端口号。
    • 使用 recvfrom 函数接收数据报,当有广播数据到达时,接收端就能接收到。
4.2.2 直接广播原理
  1. 发送端

    • 同样,发送端先创建 UDP 套接字并设置允许广播选项。
    • 构造 UDP 数据报时,将目的 IP 地址设置为目标网络的直接广播地址,目的端口号设置为接收端监听的端口号。
    • 使用 sendto 函数发送数据报,路由器会将该数据报转发到目标网络的所有主机。
  2. 接收端

    • 接收端在目标网络内,创建 UDP 套接字并绑定到指定端口号。
    • 使用 recvfrom 函数接收数据报,接收来自发送端的广播数据。

4.3 流程示意图

4.3.1 有限广播流程示意图
设置套接字为广播模式
发送有限广播数据报
广播数据
广播数据
广播数据
发送端
构造有限广播数据报 目的地址255.255.255.255
本地网络
接收端1
接收端2
接收端3
4.3.2 直接广播流程示意图
设置套接字为广播模式
发送直接广播数据报
路由器转发数据报
广播数据
广播数据
广播数据
发送端
构造直接广播数据报 目的地址 目标网络广播地址
网络 含路由器
目标网络
接收端1
接收端2
接收端3

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 1024

int 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 1024

int 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 1024

int 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 1024

int 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 编译和测试过程

  1. 编译
    • 有限广播
      • 在终端中,切换到包含 udp_limited_broadcast_sender.cudp_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.cudp_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
  2. 测试
    • 有限广播
      • 首先在本地网络内的多个终端中运行接收端程序:./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!

五、UDP 多播

5.1 概念描述

UDP 多播(也称为组播)是一种一对多的通信方式,发送端向一组特定的接收端发送数据。这组接收端通过加入同一个多播组来接收数据。多播使用 D 类 IP 地址(范围是 224.0.0.0 到 239.255.255.255)来标识多播组。发送端将数据发送到多播组的 IP 地址,网络会将数据转发给组内的所有成员。多播适用于一些需要向特定的一组设备发送相同数据的场景,如在线视频会议、流媒体分发等。与广播不同,多播不会向网络中的所有设备发送数据,只有加入了相应多播组的设备才会接收数据,这样可以减少网络流量,提高传输效率。

5.2 原理

  1. 发送端

    • 发送端创建 UDP 套接字。
    • 构造 UDP 数据报时,将目的 IP 地址设置为多播组的 IP 地址,目的端口号设置为接收端监听的端口号。
    • 使用 sendto 函数将数据报发送出去,网络会根据多播路由协议将数据转发到多播组的成员。发送端不需要关心组内成员的具体 IP 地址,只需要知道多播组的地址。
  2. 接收端

    • 接收端创建 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 流程示意图

构造多播数据报
多播数据
转发多播数据
转发多播数据
多播数据
发送端
发送多播数据
网络
接收端1 已加入组
接收端2 已加入组
未加入组的设备 忽略

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 1024

int 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 1024

int 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 编译和测试过程

  1. 编译

    • 在终端中,切换到包含 udp_multicast_sender.cudp_multicast_receiver.c 文件的目录。
    • 编译发送端代码:gcc -o udp_multicast_sender udp_multicast_sender.c
    • 编译接收端代码:gcc -o udp_multicast_receiver udp_multicast_receiver.c
  2. 测试

    • 首先在多个终端中运行接收端程序(模拟多播组成员):./udp_multicast_receiver
    • 然后在另一个终端中运行发送端程序:./udp_multicast_sender
    • 每个接收端都将显示接收到的多播消息:`Multicast message received: Hello, Multicast Group!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CamemBERT:一款出色的法语语言模型

摘要 预训练语言模型在自然语言处理中已无处不在。尽管这些模型取得了成功&#xff0c;但大多数可用模型要么是在英语数据上训练的&#xff0c;要么是在多种语言数据拼接的基础上训练的。这使得这些模型在除英语以外的所有语言中的实际应用非常有限。本文探讨了为其他语言训练…

基于PyQt - 6的医疗多模态大模型医疗研究系统中的创新构建与应用(上 .文章部分)

一、引言 1.1 研究背景与意义 在当今数智化时代,医疗行业正经历着深刻的变革,对智能化、高效化的需求日益迫切。传统的医疗模式在面对海量的医疗数据、复杂的诊断流程以及个性化的治疗需求时,逐渐显露出局限性。随着人工智能技术的飞速发展,多模态大模型作为一种前沿技术…

(一)afsim第三方库编译

注意&#xff1a;防止奇怪的问题&#xff0c;源码编译的路径最好不要有中文&#xff0c;请先检查各文件夹名 AFSIM版本 Version&#xff1a; 2.9 Plugin API Version&#xff1a; 11 软件环境 操作系统&#xff1a; Kylin V10 SP1 项目构建工具: cmake-3.26.0-linux-aarch6…

【NextJS】PostgreSQL 遇上 Prisma ORM

NextJS 数据库 之 遇上Prisma ORM 前言一、环境要求二、概念介绍1、Prisma Schema Language&#xff08;PSL&#xff09; 结构描述语言1.1 概念1.2 组成1.2.1 Data Source 数据源1.2.2 Generators 生成器1.2.3 Data Model Definition 数据模型定义字段(数据)类型和约束关系&…

细说STM32F407单片机电源低功耗SleepMode模式及应用示例

目录 一、STM32F4的低功耗模式 1、睡眠(Sleep)模式 2、停止(Stop)模式 3、待机(Standby)模式 二、睡眠模式 1、进入睡眠模式 2、睡眠模式的状态 3、退出睡眠模式 4、SysTick的影响 三、应用示例 1、工程配置 &#xff08;1&#xff09; 时钟、DEBUG、GPIO、CodeGen…

YOLOv11改进,YOLOv11检测头融合RepConv卷积,并添加小目标检测层(四头检测),适合目标检测、分割等任务

摘要 作者提出了一种简单而强大的卷积神经网络架构,其推理阶段采用与 VGG 类似的网络体结构,仅由一堆 3x3 卷积和 ReLU 组成,而训练阶段的模型具有多分支拓扑。这种训练阶段和推理阶段架构的解耦通过结构重参数化技术实现,因此我们将该模型命名为 RepVGG。 # 理论介绍 Re…

ScratchLLMStepByStep:训练自己的Tokenizer

1. 引言 分词器是每个大语言模型必不可少的组件&#xff0c;但每个大语言模型的分词器几乎都不相同。如果要训练自己的分词器&#xff0c;可以使用huggingface的tokenizers框架&#xff0c;tokenizers包含以下主要组件&#xff1a; Tokenizer: 分词器的核心组件&#xff0c;定…

Linux 操作二:文件映射与文件状态

Linux 操作二&#xff1a;文件映射与文件状态查询 文件映射 ​ mmap是一种内存映射文件的方法&#xff0c;即将一个文件或者其它对象映射到进程的地址空间&#xff0c;实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后&#xff0c;进程…

网络编程-TCP套接字

文章目录 初始TCP套接字TCP的Socket APISocketServerSocket 使用TCP模拟通信服务器端客户端 上述测试代码的问题分析IO的输入缓冲区的问题关于TCP协议中的粘包的问题不能进行多线程通信的问题 处理问题之后的完整代码启动多个实例完整代码测试结果 关于IO多路复用机制的引入 初…

flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈

flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈 开发背景 可能大家听过过蓝湖可以转ui设计图为vue.js&#xff0c;react native代码&#xff0c;那么请问听说过将figma的设计图转换为flutter源代码吗?本文优雅草央千澈带…

重拾Python学习,先从把python删除开始。。。

自己折腾就是不行啊&#xff0c;屡战屡败&#xff0c;最近终于找到前辈教我 第一步 删除Python 先把前阵子折腾的WSL和VScode删掉。还是得用spyder&#xff0c;跟matlab最像&#xff0c;也最容易入手。 从VScode上搞python&#xff0c;最后安装到appdata上&#xff0c;安装插…

【机器学习实战中阶】音乐流派分类-自动化分类不同音乐风格

音乐流派分类 – 自动化分类不同音乐风格 在本教程中,我们将开发一个深度学习项目,用于自动化地从音频文件中分类不同的音乐流派。我们将使用音频文件的频率域和时间域低级特征来分类这些音频文件。 对于这个项目,我们需要一个具有相似大小和相似频率范围的音频曲目数据集…

[Qt]事件-鼠标事件、键盘事件、定时器事件、窗口改变事件、事件分发器与事件过滤器

目录 前言&#xff1a;Qt与操作系统的关系 一、Qt事件 1.事件介绍 2.事件的表现形式 常见的Qt事件&#xff1a; 常见的事件描述: 3.事件的处理方式 处理鼠标进入和离开事件案例 控件添加到对象树底层原理 二、鼠标事件 1.鼠标按下和释放事件&#xff08;单击&#x…

后盾人JS -- 好用的 JavaScript Symbol 类型

Symbol使用场景介绍 举个例子&#xff0c;当leader让你去机房取某个电脑的时候&#xff0c;机房那么多电脑&#xff0c;你怎么知道取哪个 所以这个时候symbol的作用就显现出来了&#xff08;上面有什么贴纸的&#xff0c;什么型号的电脑&#xff09; 声明定义Symbol的几种方…

社区版Dify实现文生视频 LLM+ComfyUI+混元视频

社区版Dify实现文生视频 LLMComfyUI混元视频 一、 社区版Dify实现私有化混元视频效果二、为什么社区版Dify可以在对话框实现文生视频&#xff1f;LLMComfyUI混元视频 实现流程图&#xff08;重点&#xff09;1. 文生视频模型支持ComfyUI2. ComfyUI可以轻松导出API实现封装3. Di…

数智化转型 | 星环科技Defensor 助力某银行数据分类分级

在数据驱动的金融时代&#xff0c;数据安全和隐私保护的重要性日益凸显。某银行作为数字化转型的先行者&#xff0c;面临着一项艰巨的任务&#xff1a;如何高效、准确地对分布在多个业务系统、业务库与数仓数湖中的约80万个字段进行数据分类和分级。该银行借助星环科技数据安全…

Spring boot启动原理及相关组件

优质博文&#xff1a;IT-BLOG-CN 一、Spring Boot应用启动 一个Spring Boot应用的启动通常如下&#xff1a; SpringBootApplication Slf4j public class ApplicationMain {public static void main(String[] args) {ConfigurableApplicationContext ctx SpringApplication.…

中国石油大学(华东)自动评教工具(涵盖爬虫的基础知识,适合练手)

我开发了一个用于自动评教的工具&#xff0c;大家可以试着用用&#xff0c;下面是链接。 https://github.com/restrain11/auto_teachingEvaluate 可以点个星吗&#xff0c;感谢&#xff01;&#x1fae1; 以下是我在开发过程中学到的知识 以及 碰到的部分问题 目录 动态爬虫和静…

PyTorch使用教程(2)-torch包

1、简介 torch包是PyTorch框架最外层的包&#xff0c;主要是包含了张量的创建和基本操作、随机数生成器、序列化、局部梯度操作的上下文管理器等等&#xff0c;内容很多。我们基础学习的时候&#xff0c;只有关注张量的创建、序列化&#xff0c;随机数、张量的数学数学计算等常…

机器学习-距离的度量方法

文章目录 一. 欧式距离二. 曼哈顿距离三. 切比雪夫距离四. 闵式距离1. p不同取值,表示不同距离2. 当 ( p → ∞ ) ( p \to \infty ) (p→∞) 时&#xff0c;为什么闵式距离变为切比雪夫距离 五. 总结 一. 欧式距离 欧式距离&#xff08;Euclidean distance&#xff09;:多维空…