news 2026/4/15 13:11:28

Linux网络编程-UDP 组播原理与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux网络编程-UDP 组播原理与实战

一、UDP 组播核心概念

UDP 通信有三种典型模式,组播是单播和广播的中间形态,能精准向指定一组主机通信,大幅节省网络带宽:

通信模式特点适用场景
单播一对一(两台主机端对端通信)精准的点对点数据传输(如 TCP 连接、UDP 单主机通信)
广播一对所有(向局域网所有主机发数据)需局域网全量通知的场景(如 DHCP 地址分配)
组播一对一组(向特定主机组发数据)音视频流推送、多设备协同等场景

组播核心特性

  1. 一台主机可同时加入多个组播组;
  2. 组播既支持局域网通信,也可用于广域网(需路由器支持组播路由);
  3. 组播 / 广播属性默认关闭,需通过setsockopt()手动开启;
  4. 多播地址仅能作为目的地址,不能作为源地址(和广播地址特性一致);

二、IPv4 组播地址(D 类地址)

IP 组播通信依赖专属的 D 类 IP 地址,范围224.0.0.0 ~ 239.255.255.255,分为三类:

地址分类范围核心特点
局部链接多播地址224.0.0.0 ~ 224.0.0.255① 路由协议 / 特殊用途预留;② 路由器不转发;③ 仅局域网可用,不可用于公网
预留多播地址224.0.1.0 ~ 238.255.255.255① 用户可用的临时组地址;② 可用于 Internet 公网
管理权限多播地址239.0.0.0 ~ 239.255.255.255① 组织内部专用;② 类似私有 IP;③ 不可用于公网

三、UDP 组播代码实现

3.1 发送方(Sender.cpp)

核心要点

  • 无需绑定(bind)端口;
  • 目标地址使用组播地址(示例:224.0.0.88);
  • 循环发送组播数据,模拟持续推送场景。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { char buf[BUFSIZ]; // 1. 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { perror("socket"); exit(1); } // 2. 配置组播目标地址(组播地址+端口) struct sockaddr_in peer; peer.sin_family = AF_INET; // IPv4协议 peer.sin_port = htons(9000); // 组播端口(需和接收方一致) peer.sin_addr.s_addr = inet_addr("224.0.0.88"); // 组播地址 printf("准备发送组播数据...\n"); // 3. 循环发送组播消息(模拟持续推送) for (int i = 1; ; i++) { sprintf(buf, "新年好,第 %d 次问候!", i); int ret = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&peer, sizeof(peer)); printf("had send %d bytes: %s\n", ret, buf); sleep(1); // 每秒发送一次 } close(sockfd); // 实际循环不会执行到这里 return 0; }

3.2 接收方(Receiver.cpp)

核心要点

  • 必须绑定(bind)端口和INADDR_ANY地址;
  • 通过IP_ADD_MEMBERSHIP加入指定组播组;
  • 接收指定次数数据后,通过IP_DROP_MEMBERSHIP退出组播组;
  • 测试退出组播组后是否还能接收组播数据。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { char buf[BUFSIZ]; // 1. 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { perror("socket"); exit(1); } // 2. 绑定端口(接收方必须bind) struct sockaddr_in addr; addr.sin_family = AF_INET; // IPv4协议 addr.sin_port = htons(9000); // 和发送方一致的组播端口 addr.sin_addr.s_addr = INADDR_ANY; // 接收本机所有网卡的组播数据 int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); if (-1 == ret) { perror("bind"); exit(1); } // 3. 配置组播组信息(要加入的组播地址+本地网卡) struct ip_mreq req; req.imr_multiaddr.s_addr = inet_addr("224.0.0.88"); // 要加入的组播地址 req.imr_interface.s_addr = INADDR_ANY; // 本机所有网卡 // 4. 加入组播组 ret = setsockopt( sockfd, IPPROTO_IP, // IP层协议 IP_ADD_MEMBERSHIP, // 加入组播组的选项 &req, sizeof(req)); if (ret < 0) { perror("setsockopt(IP_ADD_MEMBERSHIP)"); exit(1); } // 5. 接收10次组播数据(加入组播组期间) printf("已加入组播组,开始接收数据...\n"); for(int i=0; i<10; i++) { struct sockaddr_in from; socklen_t len = sizeof(from); ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&from, &len); printf("【加入组播组】recv from: %s:%d -> %s\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); } // 6. 退出组播组 ret = setsockopt( sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, // 退出组播组的选项 &req, sizeof(req)); if (ret < 0) { perror("setsockopt(IP_DROP_MEMBERSHIP)"); exit(1); } // 7. 测试退出组播组后是否能接收数据(理论上收不到) printf("已退出组播组,尝试接收数据...\n"); for(int i=0; i<10; i++) { struct sockaddr_in from; socklen_t len = sizeof(from); ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&from, &len); printf("【退出组播组】recv from: %s:%d -> %s\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); } close(sockfd); return 0; }

四、编译与测试

4.1 编译命令

# 编译发送方 g++ Sender.cpp -o sender # 编译接收方 g++ Receiver.cpp -o receiver

4.2 测试步骤

  1. 启动接收方:在 1 台或多台同一局域网的主机上执行接收程序
    ./receiver
  2. 启动发送方:在任意主机执行发送程序
    ./sender
  3. 观察结果
    • 接收方前 10 次能正常收到组播数据;
    • 退出组播组后,后续无法接收组播数据(recvfrom 会阻塞)。

总结

  1. UDP 组播是 “一对一组” 通信,相比广播能大幅节省带宽,支持局域网 / 广域网使用;
  2. 组播依赖 IPv4 D 类地址(224.0.0.0~239.255.255.255),不同段地址有不同使用范围;
  3. 组播接收方必须 bind 端口,且需通过IP_ADD_MEMBERSHIP加入组播组,退出需用IP_DROP_MEMBERSHIP,发送方无需 bind 仅需指定组播地址。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/3 4:31:17

什么是RPKI

文章目录为什么需要RPKIRPKI是如何工作的RPKI功能扩展RPKI&#xff08;Resource Public Key Infrastructure&#xff0c;资源公钥基础设施&#xff09;是一种基于PKI&#xff08;Public Key Infrastructure&#xff0c;公钥基础设施&#xff09;的技术&#xff0c;专门用于验证…

作者头像 李华
网站建设 2026/4/14 10:20:13

销售额飙涨 2.5 倍,TACOS 直降 10 点!DeepBI 助力亚马逊卖家高效破局

亚马逊美国站卖家&#xff0c;谁没遇到过 “卖得多、赚得少” 的尴尬&#xff1f;深圳一家深耕美国站点的工厂卖家&#xff0c;就曾面临这样的困境——5月广告总销售额虽高&#xff0c;ACOS却高达30.58%&#xff0c;运营成本居高不下。直到邂逅DeepBI智能AI广告系统&#xff0c…

作者头像 李华
网站建设 2026/4/12 12:25:42

稠密、稀疏与MoE:大模型时代的三重架构革命

稠密、稀疏与MoE&#xff1a;大模型时代的三重架构革命当模型规模遇到物理极限&#xff1a;参数爆炸的困境想象一下建造一座摩天大楼。传统方法&#xff08;稠密模型&#xff09;就像用实心钢材建造每个楼层——结构坚固但极其沉重&#xff0c;很快会遇到地基承重极限。现代方法…

作者头像 李华
网站建设 2026/4/12 20:30:03

大数据情感分析:让广告更具情感吸引力

大数据情感分析&#xff1a;让广告从“无感”到“共情”的技术密码 一、引言&#xff1a;为什么你刷到的广告&#xff0c;总像在“喊口号”&#xff1f; 清晨地铁上&#xff0c;你刷到一条汽车广告&#xff1a;“XXSUV&#xff0c;动力强&#xff0c;空间大”——翻了个白眼划走…

作者头像 李华
网站建设 2026/4/15 7:11:14

人工智能基础层——支撑“AI+千行百业”落地的核心引擎

2026年作为“十五五”规划的开局之年&#xff0c;明确释放“推动人工智能全方位赋能千行百业”的核心信号&#xff0c;全面实施“人工智能”行动&#xff0c;推动人工智能与产业发展、文化建设、民生保障、社会治理深度融合&#xff0c;抢占产业应用制高点。 在此背景下&#…

作者头像 李华