组播详解及示例代码

article/2025/8/22 15:07:44

写在前面

由于公司业务需要用到组播实现,这里就记录下学习过程。在学习组播之前,我们先来看看另外两种数据包传输方式:单播和广播

  1. 单播:简单来说就是数据一对一发送,如果需要给多个主机发送数据时,就需要将同一份源数据的多次拷贝,发送给这些主机。无疑加重了源主机以及网络带宽的压力。这种传输方式不利于批量传输数据。
  2. 广播:不需要这些信息的主机也会收到该信息,数据的安全性得不到保证,还会造成同一网段内的信息泛滥,浪费带宽。可以看到,这种传输方式不利于给特定的用户传输数据。

一、什么是组播

组播(Multicast),又称“多播”,是一种数据包传输方式。它以"尽力而为"的形式发送信息到某个目标组,这个目标组称为组播组。

源主机向多个主机发送数据时,源主机只发送一份数据,数据的目的地址是组播组地址。这样,凡是属于该组的成员,都可以接收到一份源主机发送的数据的拷贝,此组播方式下,只有真正信息需要的成员会收到信息,其他主机不会收到。

组播相较于单播和广播的优势:

  1. 相较于单播,被传递的信息只会在距信息源尽可能远的网络节点才开始被复制和分发,用户的增加不会导致信息源负载的加重以及网络资源消耗的显著增加
  2. 相较于广播,被传递的信息只会发送给需要该信息的接收者,所以不会造成网络资源的浪费,并能提高信息传输的安全性

小结:当有多台主机同时成为一个数据包的接受者时,出于对带宽和CPU负担的考虑,组播成为了一种最佳选择。

1.1 组播相关术语

  • 组播组:用组播地址标识的一组主机集合
  • 组播源:数据的发送者
  • 组播成员:加入某个组播组的主机
  • 组播路由器:运行组播协议的设备

1.2 组播如何工作

组播通过把224.0.0.0-239.255.255.255的D类地址作为目的地址,有一台源主机发出目的地址是以上范围组播地址的报文,在网络中,如果有其他主机对于这个组的报文有兴趣的,可以申请加入这个组,并可以接受这个组,而其他不是这个组的成员是无法接受到这个组的报文的。
在这里插入图片描述

1.3 组播实现原理

上面说到了组播路由器,这里我们着重看下这个组播路由器的作用。

用户根据IGMP协议发送请求报文,路由器收到IGMP报文后,会把用户加入自己的组播组,组播报文到达路由器时,根据组播组复制多份数据发给组内的所有主机。

注意:IGMP报文并不是发给路由器,它的目的地址只有目标主机,报文从用户到目标主机可能经历多个路由器,用户必须加入这些路由器的组播组,为什么呢?因为只有用户加入了这条路径上所有的路由器的组播组之后,组播源发出的数据,才能在经过层层路由是转发到正确的目标用户。

发送IGMP报文需要知道组播源的IP地址,那用户是如何知道组播源的IP地址的呢?答案是:RP(Rendezvous Point)集中点,具体来说就是,让组播源知道RP的IP地址,让用户知道RP的IP地址。

获取组播源IP地址

在这里插入图片描述

  1. 组播源通过单播的方式把组播 239.0.0.2 封装在一个单播发送给RP(src_ip: 192.168.60.213, dst_ip: 192.168.60.210)
  2. 用户D向RP发送请求加入组播239.0.0.2 的IGMP报文
  3. RP收到请求后,把组播源发送的单播数据复制一份发送给用户D
  4. 用户D收到报文后解析就能拿到组播源的IP地址192.168.60.213
组播实现

在这里插入图片描述

  1. 接收端发送IGMP报文给组播源,经过的所有路由器都会把接受端加入组播组239.0.0.2
  2. 组播源发送数据到组播组 239.0.0.2
  3. 路由器收到数据,具体发给谁由路由器的路由表决定

二、组播代码示例

2.1 server端(组播源)

MulticastServer.h

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <errno.h>
#include <string>#define SERVER_PORT 8000
#define CLIENT_PORT 9000
#define GROUP "239.0.0.2"using namespace std;class MulticastServer{
public:MulticastServer();~MulticastServer();bool Init();void SendMessage(string payloadMessage);private:int m_sockfd;struct sockaddr_in m_serveraddr, m_clientaddr;
};

MulticastServer.cpp

#include "MulticastServer.h"bool MulticastServer::Init()
{m_sockfd = socket(AF_INET, SOCK_DGRAM, 0);                /*构造用于UDP通信的套接字*/bzero(&m_serveraddr, sizeof(m_serveraddr));m_serveraddr.sin_family = AF_INET;                        /* IPv4 */m_serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);         /*本地任意IP INADDR_ANY = 0 */m_serveraddr.sin_port = htons(SERVER_PORT);bind(m_sockfd, (struct sockaddr *)&m_serveraddr, sizeof(m_serveraddr));struct ip_mreqn group;inet_pton(AF_INET, GROUP, &group.imr_multiaddr);        /*设置组播组的地址*/inet_pton(AF_INET, "0.0.0.0", &group.imr_address);      /* 本地任意IP 自动分配有效IP*/group.imr_ifindex = if_nametoindex("enp5s0");             /* 给出网卡名,转换为对应编号:eth0 --> 编号         ,,  命令:ip ad */int ret = setsockopt(m_sockfd, IPPROTO_IP, IP_MULTICAST_IF, &group, sizeof(group));  /*获取组播权限*/if (ret < 0) {printf("Fail to disable multicast loop, err: %s",strerror(errno));return false;}else{printf("disable multicast loop success.\n");}// ret = setsockopt(m_sockfd, IPPROTO_IP , IP_MULTICAST_LOOP, &group, sizeof(group));bzero(&m_clientaddr, sizeof(m_clientaddr));                 /* 构造client 地址 IP+端口号*/m_clientaddr.sin_family = AF_INET;inet_pton(AF_INET, GROUP, &m_clientaddr.sin_addr.s_addr); /* IPv4  239.0.0.2+9000 */m_clientaddr.sin_port = htons(CLIENT_PORT);return true;
}void MulticastServer::SendMessage(string payloadMessage)
{// sprintf(buf, "from 192.168.60.213 server info: multicast %d\n", i++);//fgets(buf, sizeof(buf), stdin);sendto(m_sockfd, (char*)payloadMessage.c_str(), payloadMessage.size(), 0, (struct sockaddr *)&m_clientaddr, sizeof(m_clientaddr));
}

main.c

#include "MulticastServer.h"int main(int argc, char *argv[])
{MultiBroadcastServer server;server.init();int idx = 0;while(true){idx++;std::string msg = "from 192.168.60.213 server info: multicast " + to_string(idx) + "\n";server.SendMessage(msg);sleep(1);}return 0;
}

2.2 client端(接收端)

MulticastClient.h

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <errno.h>
#include <string>#define SERVER_PORT 8000
#define CLIENT_PORT 9000
#define GROUP "239.0.0.2"using namespace std;class MulticastClient{
public:MulticastClient();~MulticastClient();bool Init();void recvMessage(char* buffer, int &len);private:int m_confd;struct sockaddr_in m_clientaddr;
};

MulticastClient.cpp

#include "MulticastClient.h"bool MulticastClient::Init()
{struct ip_mreqn group;                                                  /*组播结构体*/m_confd= socket(AF_INET, SOCK_DGRAM, 0);bzero(&m_clientaddr, sizeof(m_clientaddr));                                   /* 初始化*/m_clientaddr.sin_family = AF_INET;inet_pton(AF_INET, "0.0.0.0" , &m_clientaddr.sin_addr.s_addr);m_clientaddr.sin_port = htons(CLIENT_PORT);bind(m_confd, (struct sockaddr *)&m_clientaddr, sizeof(m_clientaddr));inet_pton(AF_INET, GROUP, &group.imr_multiaddr);                        /* 设置组播组地址*/inet_pton(AF_INET, "0.0.0.0", &group.imr_address);                      /*使用本地任意IP添加到组播组*/group.imr_ifindex = if_nametoindex("enp5s0");                             /* 设置网卡名 编号 ip ad */    setsockopt(m_confd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group));/* 将client加入组播组*/return true;
}void MulticastClient::recvMessage(char* buffer, int &len)
{len = recvfrom(m_confd, buffer, BUFSIZ, 0, NULL, 0);std::cout << "client recv: " << std::string(buffer) <<  " , len : "<<  len << std::endl;
}

main.c

#include "MulticastClient.h"int main(int argc, char *argv[])
{MulticastClient client;client.init();while(true){char buffer[BUFSIZ] = {0};int len = 0;client.recvMessage(buffer, len);usleep(10*1000);}return 0;
}

推荐一个零声学院免费教程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:


http://chatgpt.dhexx.cn/article/NmCE6MS7.shtml

相关文章

组播的简单介绍

一、组播部署背景 1、广播方式部署点到多点应用 广播方式所存在的问题&#xff1a; ①地域范围限制 ②安全性无法保障 ③有偿性无法保障 2、单播方式部署点到多点应用 单播方式所存在的问题&#xff1a; ①重复流量过多 ②消耗设备和链路带宽资源 ③难以保证传输质量 3、组播方…

什么是组播-网工必会的组播基础概念详解

什么是组播-网工必会的组播基础概念详解 什么是组播?组播方式解决了单播情况下数据的重复拷贝及带宽的重复占用&#xff0c;也解决了广播方式下带宽资源的浪费,下面腾科教育小编给大家科普一些网工必会的组播基础概念详解。 单播一对多通信场景 1.在单播(Unicast)通信中每一个…

组播基础概念

概述&#xff1a; 组播传输作为IP数据传输的三种方式之一 &#xff0c;是指接收者的数量和位置在源端主机不知道的情况下&#xff0c;仅由源发出一份组播报文&#xff0c;向目标组播IP地址发送数据的过程。其特点有&#xff1a; 组播实现点到多点的高效数据传输。&#xff08…

最新蓝奏云软件库系统源码分享下载+非WebView

正文: 蓝奏云软件库&#xff0c;添加分类填入蓝奏云文件夹分享链接&#xff0c;链接密码即可。 非webview为接口式获取文件列表&#xff0c;不存储本地&#xff0c;只用在蓝奏云上传文件即可。 后端 thinkphp&#xff0c;前端 uniapp&#xff08;我测试了下发现没有前端源…

ThinkPHP高仿蓝奏云网盘系统程序

搭建教程&#xff1a; 1.修改数据库config/database.php 2.导入打包的数据库文件 3.设置为pcblic运行目录 4.上面全部设置好了就可以后台登入地址&#xff1a;域名/admin.php 账号adminz密码548717398 5.伪静态设置 <IfModule mod_rewrite.c>RewriteEngine onRewriteBa…

2023最新仿蓝奏云合集下载页面系统源码 带后台版本

2023最新仿蓝奏云合集下载页面系统源码 带后台版本 新版仿蓝奏云合集下载页源码续上次发的仿蓝奏云合集下载单页源码 修复了搜索功能 修复无法下载文件和下载文件为空 更新功能如下 1.增加后台 2.可在后台上传文件及删除文件等信息修改 3.目前仅支持apk,zip,exe,rat,txt文件 4…

如何把蓝奏云里的文件进行批量导出分享?蓝奏云批量分享的工具

蓝奏云用的的多了&#xff0c;里面文件管理起来就非常的麻烦&#xff0c;在这里分享一下如何方便得批量分享蓝奏云中的文件。 首先需要下载一个软件 简单麦麦客户端 下载地址在 https://gitee.com/firesuiry/jdmm-client/releases 是个开源的软件 有兴趣可以研究研究 下载完…

php 蓝奏网盘上传文件,教给大家一个蓝奏云高级玩法,如何把文件一键秒上传到蓝奏云网盘...

01 蓝奏云是我最常用的网盘平台 当然这也是在度盘限速之后 毕竟&#xff0c;蓝奏也有几个很大的短板 但整体上是利大于弊&#xff01; 好处就是&#xff0c;整个网盘空间没有上限 不论你上传多少个文件、他都不拦你 另外一点&#xff0c;下载永远都是满速状态 这个真的太香了&a…

解决蓝奏云链接无法访问问题

方法一&#xff1a;修改蓝奏云链接域名 将www.lanzous 后面的 s 改为 x 或者改为 i &#xff0c;www.lanzoux&#xff0c;然后再访问链接即可正常访问。 方法二&#xff1a;油候脚本自动转换蓝奏云链接 脚本地址&#xff1a;蓝奏云连接转换这款脚本可以将蓝奏云网盘链接自动…

【油猴脚本】鼠标选中跳转蓝奏云有效链接及自动填写提取码

简述 鼠标选中蓝奏云链接时会将链接转化为有效链接并显示跳转按钮&#xff0c;如果选中内容包括提取码则会在对应的网页自动填充。 地址&#xff1a;鼠标选中跳转蓝奏云有效链接及自动填写提取码 功能 在鼠标选中的文字是蓝奏云链接时触发脚本&#xff0c;脚本将从选中文字中…

解决:蓝奏云下载链接没法打开问题

假设链接如下&#xff1a; https://wws.lanzous.com/b01hnxn7a 解决: 修改链接&#xff1a;将链接中的lanzous改为lanzoux https://wws.lanzous.com/b01hnxn7a https://wws.lanzoux.com/b01hnxn7a

php蓝奏云网盘源码,蓝奏云网盘pc版易语言开源软件源码

蓝奏云盘是由网友开发的蓝奏云网盘客户端软件&#xff0c;软件界面简洁&#xff0c;简单易用 很多人喜欢&#xff0c;所以大家找了&#xff0c;蓝奏云网盘PC客户端开源源码&#xff0c;此软件源代码全部为 易语言5.6版本编写。 蓝奏云盘源码特色&#xff1a; 1.支持上传任意文件…

蓝奏云直链解析php,【带源码】新思路--蓝奏云直链解析

本帖最后由 Ls30 于 2018-7-11 18:06 编辑 今天在我的群上看到了个买 的还留下了个链接&#xff0c; 打开后我的手机浏览器跳转到了蓝奏云的一个下载页面&#xff0c; 惊奇的发现手机打开这个下载页面与电脑端的不同&#xff0c; 我猜测这是否与电脑端的解析方式有着一定的联系…

【实用软件】蓝奏云批量下载工具

软件介绍 蓝奏是个非主流网盘&#xff0c;老司机们用的比较多&#xff0c;官方限制最大上传文件为100M&#xff0c;不能分享视频等大文件&#xff0c;限制了它的用处。一般应用于分享软件&#xff0c;小型文档&#xff0c;除了下载页面有广告之外&#xff0c;下载速度很快&…

蓝奏云无视密码强制下载器

介绍&#xff1a; 可以强制下载有带密码的蓝凑云链接&#xff0c;只支持直接的分享链接&#xff08;就是蓝凑云的域名加后面的分享的那一段&#xff0c;像我下面图一有那个tp就得把他删除&#xff09;要使用软件内的下载文件&#xff0c;就要打开悬浮窗&#xff01;&#xff0…

蓝奏云软件库源码分享下载

介绍&#xff1a; 蓝奏云软件库&#xff0c;添加分类填入蓝奏云文件夹分享链接&#xff0c;链接密码即可。 非 webview 为接口式获取文件列表&#xff0c;不存储本地&#xff0c;只用在蓝奏云上传文件即可。 后端 thinkphp&#xff0c;前端 uniapp&#xff08;我测试了下发现…

蓝奏云分享文件无法下载地址失效的解决办法

由于蓝奏盘的分享地址经常失效和更改&#xff0c;导致我们分享的下载地址打不开&#xff0c;很多人不知道怎么回事&#xff0c;老是问我蓝奏云下载链接打不开怎么办&#xff0c;今天就给大家讲讲怎么解决这个问题。 解决办法&#xff1a; 如果你打开别人分享的蓝奏云提示的是是…

蓝奏云直链解析

[玫瑰]蓝奏云直链获取在线解析网站源码 蓝奏云链接解析 本地API接口 [玫瑰]支持有无密码和短期直链和永久直链&#xff0c;同时还可以显示文件名和大小。 [玫瑰]这个解析器无需数据库即可搭建&#xff0c;API接口已经本地化&#xff0c;非常简单易用。 [玫瑰]解压密码 123321 链…

Linux下载蓝奏云文件,蓝奏云CMD控制台

蓝奏云CMD控制台是一个蓝奏云的第三方API客户端&#xff0c;封装了对蓝奏云的基本操作: 登录、列出文件、下载文件、上传文件、删除文件(夹)、 清空回收站、恢复文件、创建文件夹、设置文件(夹)访问密码。此外&#xff0c;还解决了蓝奏云的上传格式限制和单文件最大 100MB 的限…

蓝奏云下载地址解析API[直链]

3 月&#xff0c;跳不动了&#xff1f;>>> 介绍 蓝奏云下载地址解析API 模拟蓝奏云真实操作获取下载地址. 下载地址:https://www.90pan.com/b1748355 密码&#xff1a;9zz7 开源地址: https://gitee.com/web/lanzou 软件架构 1.支持检测文件是否被取消 2.支持带密码…