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…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...

