UDP 多播(组播)
前言(了解分类的IP地址)


1.组播(多播)
单播地址标识单个IP接口,广播地址标识某个子网的所有IP接口,多播地址标识一组IP接口。单播和广播是寻址方案的两个极端(要么单个要么全部),多播则意在两者之间提供一种这种方案。多播数据报只应该由它感兴趣的接口接收,也就是说有运行相应多播会话的接口接收。另外,广播一般局限于局域网内使用,而多播则既可以用于局域网,也可以跨广域网使用。
- a.组播既可以用于局域网,也可以用于广域网
- b.客户端需要加入多播组,才能接收到多播组内发送的数据
1.1 单播
- 单播 是指封包在计算机网络的传输中,目的地址为单一目标的一种传输方式。
- 每次只有两个实体相互通信,发送端和接收端都是唯一确定的。
- 它是现今网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,例如一切基于是TCP的协议
单播的优点如下:
- 服务器及时响应客户及的请求
- 服务器针对每个客户不同的请求发送不同的数据,容易实现个性化服务
1.2 多播
多播 是指把信息同时传递给一组目的地址,它使用的策略是最高效的。因为 消息在每条网络链路上只需传递一次,而且只有在链路分叉的时候,消息才会被复制。当以单播的形式把消息传递给多个接收方时,必须向每个接收者都发送一份数据副本。由此产生的多余副本将导致发送方效率低下,且缺乏可扩展性。
- 多播 是指把信息同时传递给一组目的地址,它使用的策略是最高效的
- 因为 消息在每条网络链路上只需传递一次,而且只有在链路分叉的时候,消息才会被复制
- 当以单播的形式把消息传递给多个接收方时,必须向每个接收者都发送一份数据副本。
- 由此产生的多余副本将导致发送方效率低下,且缺乏可扩展性
1.2.1 多播优点与缺点
>>多播 的优点如下:
- ① 需要相同数据流的客户端加入相同的组共享一条数据流,节省了服务器的负载
- ② 由于组播协议是根据接受者的需要对数据流进行复制转发,所以服务端的服务总带宽不受 客户接入端带宽的限制。
- ③ IP协议允许有2亿6千多万个(268435456)组播,所以其提供的服务可以非常丰富
- ④ 此协议和单播协议一样允许在Internet宽带网上传输
>>多播 的缺点如下:
- ① 与单播协议相比没有纠错机制,发生丢包错包后难以弥补,但可以通过一定的容错机制和 QOS加以弥补
- ② 现行网络虽然都支持组播的传输,但在客户认证、QOS等方面还需要完善
2.组播地址
IP 多播通信必须依赖于IP多播地址,在IPv4中它的范围从224.0.0.0到239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三类

2.1 多播地址
多播地址的范围从224.0.0.0到 239.255.255.255
3.设置组播
设置组播
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);// ① 服务器设置多播的信息,外出接口- level : IPPROTO_IP- optname : IP_MULTICAST_IF- optval : struct in_addr// ② 客户端设置多播的信息,加入多播组- level : IPPROTO_IP- optname : IP_ADD_MEMBERSHIP- optval : struct ip_mreq
struct ip_mreq {/* IP multicast address of group */struct in_addr imr_multiaddr;/* Local IP address of interface */struct in_addr imr_interface;
}
4.组播代码
>>实验一
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>int main() {// 1.创建一个通信的socketint fd = socket(PF_INET, SOCK_DGRAM, 0);if(fd == -1) {perror("socket");exit(-1);} // 2.设置多播的属性,设置外出接口struct in_addr imr_multiaddr;// 初始化多播地址inet_pton(AF_INET, "239.0.0.10", &imr_multiaddr.s_addr);setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &imr_multiaddr, sizeof(imr_multiaddr));// 3.初始化客户端的地址信息struct sockaddr_in cliaddr;cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(9999);inet_pton(AF_INET, "239.0.0.10", &cliaddr.sin_addr.s_addr);// 3.通信int num = 0;while(1) {char sendBuf[128];sprintf(sendBuf, "hello, client....%d\n", num++);// 发送数据sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));printf("组播的数据:%s\n", sendBuf);sleep(1);}close(fd);return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>int main() {// 1.创建一个通信的socketint fd = socket(PF_INET, SOCK_DGRAM, 0);if(fd == -1) {perror("socket");exit(-1);} struct in_addr in;// 2.客户端绑定本地的IP和端口struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.s_addr = INADDR_ANY;int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));if(ret == -1) {perror("bind");exit(-1);}struct ip_mreq op;inet_pton(AF_INET, "239.0.0.10", &op.imr_multiaddr.s_addr);op.imr_interface.s_addr = INADDR_ANY;// 加入到多播组setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &op, sizeof(op));// 3.通信while(1) {char buf[128];// 接收数据int num = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);printf("server say : %s\n", buf);}close(fd);return 0;
}
实验二:
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>/*udp 服务器发送数据给多播组
*/int main(int argc,char *argv[]) {int sockfd;struct sockaddr_in grp_cast_addr;char wbuffer[1024];if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0) {perror("socket");exit(EXIT_FAILURE);}int wbytes;// 填充组播地址与端口号(224.0.0.8)socklen_t len = sizeof(struct sockaddr_in);memset(&grp_cast_addr,0,sizeof(grp_cast_addr));grp_cast_addr.sin_family = AF_INET;grp_cast_addr.sin_addr.s_addr = inet_addr(argv[1]);grp_cast_addr.sin_port = htons(atoi(argv[2]));while (1) {memset(wbuffer,0,sizeof(wbuffer));fprintf(stdout,"Server > ");fflush(stdout);fgets(wbuffer,sizeof(wbuffer),stdin);wbuffer[strlen(wbuffer) - 1] = '\0';// 发送给多播组(所有客户端都可以收到消息)wbytes = sendto(sockfd,wbuffer,strlen(wbuffer) + 1,0,(const struct sockaddr *)&grp_cast_addr,len);if(wbytes < 0) {perror("sendto()");break;}} close(sockfd);return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>int main(int argc,char* argv[]) {int sockfd;struct sockaddr_in local_addr; //客户端地址结构对象(自身的IP地址和端口号)struct ip_mreq mreq; //多播的地址结构体if(argc != 3) {fprintf(stderr,"Usage:%s <ip address> <port>\n",argv[0]);exit(EXIT_FAILURE);}// 1.建立 socket 文件描述符sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0) {perror("socket()");exit(EXIT_FAILURE);}// 2.将当前主机添加到多播组memset(&mreq,0,sizeof(mreq));mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);//组播的ip地址mreq.imr_interface.s_addr = htonl(INADDR_ANY); //本地ip地址,INADDR_ANY:本机上任意的IP地址// 3.修改当前的socket属性为多播属性if(setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(void*)&mreq,sizeof(mreq)) < 0){perror("setsockopt()");exit(EXIT_FAILURE);}// 4.绑定 ip 地址和端口号(自身)socklen_t len = sizeof(struct sockaddr_in);memset(&local_addr,0,sizeof(local_addr));local_addr.sin_family = AF_INET;local_addr.sin_addr.s_addr = htonl(INADDR_ANY);local_addr.sin_port = htons(atoi(argv[2]));if(bind(sockfd,(struct sockaddr*)&local_addr,len) < 0) {perror("bind()");exit(EXIT_FAILURE); }char rbuffer[1024];int rbytes;struct sockaddr_in caddr;while (1) {memset(rbuffer,0,sizeof(rbuffer));rbytes = recvfrom(sockfd,rbuffer,sizeof(rbuffer),0,(struct sockaddr*)&caddr,&len);if(rbytes < 0) {perror("recvfrom()");break;}printf("Receive from ip<%s>\n",inet_ntoa(caddr.sin_addr));printf("Receive from port<%d>\n",ntohs(caddr.sin_port));printf("Receive data: <%s>\n",rbuffer);}// 退出多播组if(setsockopt(sockfd,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {perror("setsockopt()");exit(EXIT_FAILURE);}close(sockfd);return 0;
}



知识拓展:(来自这篇文章的总结)
IP组播基础特性介绍 - NetEngine A821 E, A821, A811 M, A811, A810 V800R021C10SPC600 特性描述 - 华为 (huawei.com)
① 单播IP地址
- 一个单播IP地址只能标识一台用户主机,一台用户主机只能识别一个单播IP地址
- 一份使用单播IP地址为目的地址的IP报文,只能被一台用户主机接收
② 广播IP地址
- 一份使用单播IP地址为目的地址的IP报文,只能被一台用户主机接收
- 一份使用广播IP地址为目的地址的IP报文,能够被该网段内的所有用户主机接收
- IP广播报文不能跨网段传播
③ 组播IP地址
- 一个组播IP地址能够标识网络不同位置的多个用户主机
- 一台用户主机可以同时识别多个组播IP地址
- 一份使用组播IP地址为目的地址的IP报文,能够被网络不同位置的多个用户主机接收
推荐文章和课程:IP组播基础特性介绍 - NetEngine A821 E, A821, A811 M, A811, A810 V800R021C10SPC600 特性描述 - 华为 (huawei.com)
https://support.huawei.com/enterprise/zh/doc/EDOC1100270069/c9f73464
网络编程扩展广播与组播_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1Yk4y1b7Wz/?spm_id_from=333.337.search-card.all.click&vd_source=a934d7fc6f47698a29dac90a922ba5a3
课程列表_牛客网 (nowcoder.com)
https://www.nowcoder.com/study/live/504/4/34
网络编程36--组播和广播_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1H64y1m7YA/?spm_id_from=333.337.search-card.all.click&vd_source=a934d7fc6f47698a29dac90a922ba5a3
相关文章:
UDP 多播(组播)
前言(了解分类的IP地址) 1.组播(多播) 单播地址标识单个IP接口,广播地址标识某个子网的所有IP接口,多播地址标识一组IP接口。单播和广播是寻址方案的两个极端(要么单个要么全部)&am…...
分布式环境集成JWT(Java Web Token)
目录 一,说明:二,Token、Session和Cookie比较三,Spring Boot项目集成JWT1,引入依赖2,Token工具类3,定义拦截器4,注册拦截器5,编写登录代码6,测试 四ÿ…...
Python实战之数据表提取和下载自动化
在网络爬虫领域,动态渲染类型页面的数据提取和下载自动化是一个常见的挑战。本文将介绍如何利用Pyppeteer库完成这一任务,帮助您轻松地提取动态渲染页面中的数据表并实现下载自动化。 一、环境准备 首先,确保您已经安装了Python环境。接下来…...
Midjourney学习(三)6个高级应用
使用Remix Mode在原图片的基础上进行二次创作 通过prompt得到大图之后,点击Make Variations按钮,输入Remix Prompt,即可得到意想不到的效果! 局部内容重绘 通过局部重绘可以实现对画面内容更加精细化的控制,同样也是需…...
C语言:指针类型的意义
1.指针的类型决定了解引用时访问几个字节 2.指针的类型决定了指针1、-1跳过几个字节 一、指针的类型决定指针解引用时访问几个字节 例如 int 型指针解引用时访问4个字节 char 型指针解引用时访问1个字节 详解代码如下: int b 0x11223344(十六进制&…...
如何将 PDF 转换为 Word:前 5 个应用程序
必须将 PDF 转换为 Word 才能对其进行编辑和自定义。所以这里有 5 种很棒的方法 PDF 文件被广泛使用,因为它非常稳定且难以更改。这在处理法律合同、财务文件和推荐信等重要文件时尤其重要。但是,有时您可能需要编辑 PDF 文件。最好的方法是使用应用程序…...
AP5192 DC-DC降压恒流LED汽车头灯摩托车电动车大灯电源驱动
AP5192是一款PWM工作模式,高效率、外围简单、 内置功率MOS管,适用于4.5-100V输入的高精度 降压LED恒流驱动芯片。最大电流1.5A。 AP5192可实现线性调光和PWM调光,线性调光 脚有效电压范围0.55-2.6V. AP5192 工作频率可以通过RT 外部电阻编程 来设定&…...
Python Opencv实践 - Canny边缘检测
import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_GRAYSCALE) print(img.shape)#图像Canny边缘检测 #cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradien…...
Python编程练习与解答 练习119:低于和高于平均水平
编写一个程序,从用户处读取数字,直到用户输入空行。程序应该显示用户输入的所有值的平均值。然后所有程序应该显示所有平均值的值,然后显示所有平均值(若有),最后显示所有高于平均值的值。再每个值列表之前…...
vue中的nextTick的作用
vue里面,常用的事件onMounted里,总喜欢用一个nextTick: onMounted(() > {nextTick(() > {init();}); });这个东西有啥用呢?我总搞不懂。 今天我忽然有点明白了。这是一个跟前面语句有关的方法。意思是,等前面的…...
如何通过四个步骤清理网络防火墙规则
组织必须确保适当的安全策略到位,以保护其投资并优化其安全有效性。然而,随着网络的扩展和复杂性的增加,网络运营团队面临着管理来自多个供应商的大量防火墙和网络设备的挑战。他们必须解决分散的基础设施、职能孤岛、人员配置问题、分散的管…...
打开谷歌浏览器远程调试功能
谷歌浏览器远程调试功能 首先我们来启动Chrome的远程调试端口。你需要找到Chrome的安装位置,在Chrome的地址栏输入chrome://version就能找到Chrome的安装路径 开启远程控制命令 文件路径/chrome.exe --remote-debugging-port9222开启后的样子(注意要关闭其他谷歌浏…...
ChatGPT时代的我的博客
好久没有在CSDN写原创文章了。 ChatGPT出来之后,肯定对CSDN这样的平台有很大的冲击性。 我平时在CSDN写的文章,大多是翻译和一些平时编程遇到的代码问题。小部分是一些自己的经验和总结。 这些文章会被ChatGPT,或者更通用的说,…...
同步有关的思考。
同步通常标志着系统处于不稳定状态,所以同步过程分析和控制是非常重要的。 高速同步过程:高速同步的前提是同步源数据稳定可靠且同步过程不会破坏同步源数据的稳定性,数据接收方资源需要有足够裕量且能维持在就绪状态,双方连接链…...
Flutter Web 项目网络请求报 XMLHttpRequest error 解决方案
使用http库进行简单的网络请求时,运行在Chrome浏览器上,网络请求一直报错 XMLHttpRequest error,而在iOS 模拟器上运行则正常,后面在postman上发送请求,也是正常的。这就是很尴尬了!!࿰…...
Python面试:什么是GIL
1. GIL (Global Interpreter lock)可以避免多个线程同时执行字节码。 import threadinglock threading.Lock()n [0]def foo():with lock:n[0] n[0] 1n[0] n[0] 1threads [] for i in range(5000):t threading.Thread(targetfoo)threads.append(t)for t in threads:t.s…...
idea --Git Commit Template插件
Git Commit Template是一款免费的IntelliJ IDEA插件,用于提供Git提交模板。该插件可以帮助开发者编写规范的Git提交信息,提高代码管理效率。 首先安装插件: 使用Git Commit Template插件: 注:long description和Breaking changes…...
使用Python脚本添加新的相关节点到arxml文件中的指定位置
使用Python脚本添加新的相关节点到arxml文件中的指定位置 1 背景 随着汽车软件开发的复杂度越来越高,链路越来越长,很多手动配置的工具链所需要的时间就会被拉长,显然这对于项目的开发进度有了一定影响,根据需求自动化生成arxml文件其实很有必要。同时越来越多的测试开始…...
iOS开发Swift-闭包
1.闭包表达式语法 { (参数) -> return 类型 in//内容 }let names ["C", "A", "E", "B", "D"] func back(_ s1: String, s2: String) -> Bool {return s1 > s2 //(B > A, C > B) }//闭包后: va…...
从零开始学JAVA——常用类
常用类 课后习题一:课后练习二:课后练习三:课后练习四课后练习五: 课后习题一: 将字符串“2016-02-22”转换为对应的java.sql.Date类的对象 SimpDateFormat sdf new SimpDateFormate(“yyyy-MM-DD”); 解析 java.ut…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

