UDP 广播组播点播的区别及联系

1、网络IP地址的分类

组播地址是分类编址的IPv4地址中的D类地址,又叫多播地址,他的前四位必须是1110,所以网络地址的二进制取值范围是11100000~11101111对应的十进制为 224~~239。所以以224~239开头的网络地址都是组播地址。

组播地址的功能分类:

224.0.0.0~224.0.0.255为预留的组播地址(永久组地址)。

224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet。

224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效。

239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。

组播优势:降低网络流量,减轻硬件负荷,减少冗余流量,节约带宽。
组播应用:多媒体、任何“单到多”数据发布应用。

2、单播、组播和广播的区别

组播(Multicast, 又称多播)是UDP专有的, 关于UDP的单播(Unicast), 组播, 广播(Broadcast)的区别, 网络上有张比较形象的图如下:

组播工作原理:

1)组播使用特殊的IPv4组播地址(224.0.0.0至239.255.255.255),组播地址是一种特殊的IP地址,用于标识一个组播组。

2)Internet组管理协议(IGMP)是一种用于主机加入和离开组播组的协议。主机通过发送IGMP报文来通知路由器它们希望加入或离开一个组播组。路由器根据接收到的IGMP报文来维护组播组的成员列表。

3)路由器:组播数据的传输需要路由器的支持。路由器通过使用组播路由协议(如PIM、IGMP等)来维护组播组的成员信息,并根据这些信息将组播数据转发到适当的接口上。

4)数据传输:当一个主机发送组播数据时,它将数据包发送到一个特定的组播地址。路由器根据组播地址组员列表来确定将数据包转发到哪些接口上。只有加入了组播组的主机才会接收到组播数据。

总结:组播的原理是通过使用特定的组播地址和IGMP协议来实现多个主机之间的组播通信。路由器根据组员列表来转发组播数据,只有加入了组播组的主机才能接收到数据。组播可以提供高效的数据传输,适用于需要向多个目标主机发送相同数据的场景,如视频流、实时通信等。

3、 加入和离开组播组

3.1指令方式

加入组播组指令:sudo ip addr add 239.0.0.1 dev eth1 autojoin

离开组播组指令:sudo ip addr del 239.0.0.1/24 dev eth1 autojoin

3.2代码方式

加入组播组:加入组播组使用setsockopt设置IP_ADD_MEMBERSHIP选项。

struct ip_mreq multi_addr;
bzero(&multi_addr, sizeof(multi_addr));
multi_addr.imr_multiaddr.s_addr = inet_addr(“239.0.0.1”);
multi_addr.imr_interface.s_addr = INADDR_ANY;
setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&multi_addr, sizeof(multi_addr));

离开组播组:离开组播组使用setsockopt设置IP_DROP_MEMBERSHIP选项。

struct ip_mreq multi_addr;
bzero(&multi_addr, sizeof(multi_addr));
multi_addr.imr_multiaddr.s_addr = inet_addr(“239.0.0.1”);
multi_addr.imr_interface.s_addr = INADDR_ANY;
setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&multi_addr, sizeof(multi_addr));

4、C语言编写接收和发送udp组播数据

4.1组播数据发送

//组播发送初始化
int initUdpMultiCastSender(uint32_t localip,uint16_t localport)
{int sockfd = socket(AF_INET,SOCK_DGRAM,0);//创建套接字if (-1 == sockfd){printf("[initUdpMultiCastSender]socket fail\n");return -1;}//设置本地的组播地址和端口(注意:该port不是组播port,而是本地port)struct sockaddr_in myaddr;memset(&myaddr,0,sizeof(myaddr));myaddr.sin_family = AF_INET;myaddr.sin_port = htons(localport);myaddr.sin_addr.s_addr = localip;int bindret = bind(sockfd,(struct sockaddr *)(&myaddr),sizeof(struct sockaddr));if (-1 == bindret){perror("[initUdpMultiCastSender]bind fail\n");close(sockfd);return -1;}return sockfd;
}
//组播数据发送--注意发送的ip和port为组播ip,port
int sendUdpMultiCast(int sockfd,char *pMultiCastIp,uint16_t multicastPort,void *data,uint32_t len)
{struct sockaddr_in destAddr;destAddr.sin_family = AF_INET;destAddr.sin_addr.s_addr = inet_addr(pMultiCastIp);destAddr.sin_port = htons(multicastPort);int sendLen = sendto(sockfd,data,len,0,(struct sockaddr *)(&destAddr),sizeof(struct sockaddr));return sendLen;
}

4.2接收组播数据

	int sockfd = socket(AF_INET,SOCK_DGRAM,0);if (-1 == sockfd){perror("socket fail\n");return -3;}printf("socket succ\n");struct ip_mreq mreq;memset(&mreq,0,sizeof(struct ip_mreq));mreq.imr_interface.s_addr = htonl(INADDR_ANY);mreq.imr_multiaddr.s_addr = inet_addr(pUdpMultiCastIp);//加入组int setoptret = setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(struct ip_mreq));if (-1 == setoptret){perror("setsockopt fail\n");return -4;}printf("setsockopt ip_add_membership succ\n");struct sockaddr_in peeraddr;memset(&peeraddr,0,sizeof(struct sockaddr_in));peeraddr.sin_family = AF_INET;peeraddr.sin_addr.s_addr = inet_addr(pUdpMultiCastIp);peeraddr.sin_port = htons(udpMultiCastPort);//绑定要接收的组播地址int bindRet = bind(sockfd,(struct sockaddr *)(&peeraddr),sizeof(struct sockaddr));if (-1 == bindRet){perror("bind fail\n");return -5;}printf("bind succ\n");while(1){char buffer[1024] = {0};socklen_t addrLen = sizeof(struct sockaddr);printf("ready 2 recv\n");int recvRet = recvfrom(sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)(&peeraddr),&addrLen);if (-1 == recvRet){perror("recvfrom fail\n");break;}printf("recvfrom succ,buffer is %s\n",buffer);}

说明:接收端的代码,整体的思路就是创建socket->加入组播(本地地址和组播地址赋值给mreq)->绑定ip,port(注意,该ip和port是组播ip和组播port)->接收数据(注意,接收的ip和port为组播ip,port)。

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

    如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    mysql 学习2 MYSQL数据模型,mysql内部可以创建多个数据库,一个数据库中有多个表;表是真正放数据的地方,关系型数据库 。

    在第一章中安装 ,启动mysql80 服务后,连接上了mysql,那么就要 使用 SQL语句来 操作mysql数据库了。那么在学习 SQL语言操作 mysql 数据库 之前,要对于 mysql数据模型有一个了解。 MYSQL数据模型 在下图中 客户端 将 SQL语言&…

    10个非常基础的 Javascript 问题

    Javascript是一种用于Web开发的编程语言。JavaScript在网络的客户端上运行。 根据MDN,JavaScript(通常缩写为JS)是一种轻量级的,解释性的,面向对象的语言,具有一流的功能,并且最著名的是Web页面…

    把 PVE 下的机械硬盘(非SSD系统盘)分配给虚拟机使用

    PVE 挂在硬盘 参考 Ubuntu 24.04 LTS 空闲硬盘挂载到 文件管理器的 other locations。 在 PVE shell 中根据上面教程挂在硬盘 新建分享目录 参考 Proxmox VE(PVE)添加硬盘做存储 虚拟机新增硬盘 虚拟机 关机,按下图新增硬盘 新增硬盘…

    制作动态菜单

    动态菜单的说明 什么叫做动态菜单?动态菜单就是根据用户属于不同的角色,每个角色还有不同的菜单,左侧菜单栏会有不同的显示 前端加载流程 menu.js 修改/src/api/menu.js中的请求地址,如下所示: // 获取菜单 export…

    C语言数组详解:从基础到进阶的全面解析

    在C语言中,数组是一种基本的数据结构,用于存储多个相同类型的数据。数组的引入使得C语言能够高效地存储和操作大量数据。在任何一个C语言程序中,数组都发挥着极其重要的作用。无论是在算法实现、数据存储、还是在复杂程序的设计中&#xff0c…

    什么是COLLATE排序规则?

    在当今数字化世界中,数据的整理、比较和排序是至关重要的。在数据库管理和编程语言中,我们经常需要对字符串进行排序,以展示或处理信息。为了实现这一点,各种系统和工具提供了排序规则,其中COLLATE排序规则就是其中的一…

    【数据结构进阶】红黑树超详解 + 实现(附源码)

    🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:数据结构 目录 前言 一、红黑树介绍 二、红黑树原理详解 三、红黑树的实现 1. 节点定义 2. 红黑树类型定义及接口声明 3. 红黑树的插入(重点&a…

    计算机网络 (57)改进“尽最大努力交付”的服务

    前言 计算机网络中的“尽最大努力交付”服务是网络层的一种数据传输方式。这种服务的特点是网络层只负责尽力将数据报从源端传输到目的端,而不保证数据传输的可靠性。 一、标记与分类 为数据分组打上标记: 给不同性质的分组打上不同的标记&#x…

    ThinkPHP 8模型与数据的插入、更新、删除

    【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《2025新书 ThinkPHP 8高效构建Web应用 编程与应用开发丛书 夏磊 清华大学出版社教材书籍 9787302678236 ThinkPHP 8高效构建Web应用》【摘要 书评 试读】- 京东图书 使用VS Code开发ThinkPHP项目-CSDN博客 编程与应用开…

    【数据可视化】全国星巴克门店可视化

    🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

    密码无关认证:金融机构如何解决密码问题

    密码安全问题,依然是金融行业面临的重大挑战。尽管密码简单易用,但许多金融机构仍然依赖这种方式进行身份认证。幸运的是,随着技术的发展,密码无关认证已经成为一种更加安全、便捷的选择,它能够为数字银行带来更好的用…

    【Redis】持久化机制

    目录 前言: RDB 触发RDB持久化方法有俩种: 1.手动触发 2.自动触发 RDB文件的优缺点: AOF: AOF工作机制:​编辑 ​编辑重写机制: 前言: Redis是一个内存数据库,将数据存储在内存中&…

    Vue基础(2)

    19、组件之间传递数据 组件与组件之间不是完全独立的&#xff0c;而是有交集的&#xff0c;那就是组件与组 件之间是可以传递数据的 传递数据的解决方案就是 props ComponentA.vue <template><!-- 使用ComponentB组件&#xff0c;并传递title属性 --><h3>…

    Java操作Excel导入导出——POI、Hutool、EasyExcel

    目录 一、POI导入导出 1.数据库导出为Excel文件 2.将Excel文件导入到数据库中 二、Hutool导入导出 1.数据库导出为Excel文件——属性名是列名 2.数据库导出为Excel文件——列名起别名 3.从Excel文件导入数据到数据库——属性名是列名 4.从Excel文件导入数据到数据库…

    08-ArcGIS For JavaScript-通过Mesh绘制几何体(Cylinder,Circle,Box,Pyramid)

    目录 概述代码实现1、Mesh.createBox2、createPyramid3、Mesh.createSphere4、Mesh.createCylinder 完整代码 概述 对于三维场景而言&#xff0c;二位的点、线、面&#xff0c;三维的圆、立方体、圆柱等都是比较常见的三维对象&#xff0c;在ArcGIS For JavaScript中我们知道点…

    DAY6,使用互斥锁 和 信号量分别实现5个线程之间的同步

    题目 请使用互斥锁 和 信号量分别实现5个线程之间的同步 代码&#xff1a;信号量实现 void* task1(void* arg); void* task2(void* arg); void* task3(void* arg); void* task4(void* arg); void* task5(void* arg);sem_t sem[5]; //信号量变量int main(int argc, const …

    19_PlayerPres持久化_创建角色窗口

    创建脚本 编写脚本 using UnityEngine; //功能 : 角色创建界面 public class CreateWnd : WindowsRoot{protected override void InitWnd(){base.InitWnd();//TODO//显示一个随机名字} }创建角色窗口CreateWnd.cs应该在玩家点击 进入游戏 按钮后显示 所以在 登录窗口LoginWnd…

    热更新杂乱记

    热更新主要有一个文件的MD5值的比对过程&#xff0c;期间遇到2个问题&#xff0c;解决起来花费了一点时间 1. png 和 plist 生成zip的时候再生成MD5值会发生变动。 这个问题解决起来有2种方案&#xff1a; &#xff08;1&#xff09;.第一个方案是将 png和plist的文件时间改…

    【2024年华为OD机试】 (C卷,100分)- 用户调度问题(JavaScriptJava PythonC/C++)

    一、问题描述 问题描述 在通信系统中&#xff0c;有 n 个待串行调度的用户&#xff0c;每个用户可以选择 A、B、C 三种调度策略。不同的策略会消耗不同的系统资源。调度规则如下&#xff1a; 相邻用户不能使用相同的调度策略&#xff1a;例如&#xff0c;如果第 1 个用户选择…

    FPGA中场战事

    2023年10月3日,英特尔宣布由桑德拉里维拉(Sandra Rivera)担任“分拆”后独立运营的可编程事业部首席执行官。 从数据中心和人工智能(DCAI)部门总经理,转身为执掌该业务的CEO,对她取得像AMD掌门人苏姿丰博士类似的成功,无疑抱以厚望。 十年前,英特尔花费167亿美元真金白银…