网络编程 | UDP组播通信

1、什么是组播

        在上一篇博客中,对UDP的广播通信进行了由浅入深的总结梳理,本文继续对UDP的知识体系进行探讨,旨在将UDP的组播通信由浅入深的讲解清楚。

        组播是介于单播与广播之间,在一个局域网内,将某些主机添加到组中,并设置一个组地址。将数据发送到组播地址时,加入到该组的所有主机都能接收到数据。

        组播、单播和广播都是报文传输的一种方式。

        单播是主机间一对一的通信模式,设备只会将数据发送到唯一指定的接收者。

        广播是主机间一对所有的通信模式,设备会将数据发送到网络中的所有可能的接收者。设备简单地将它收到的任何广播报文都复制并转发到除该报文到达的接口外的每个接口。广播处理流程简单,不用选择路径。

        组播是主机间一对多的通信模式, 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。类似于生活中较为常见的群聊功能,在群内的所有群员,都可以在群内发送消息给群友,也可以接收到来自任意群友的消息。

        为了帮助读者更进一步的理解UDP的单播、组播和广播功能,绘制了如下所示的总结图。

2、IP地址分类

        因为组播通信需要设置IP地址,且必须是D类IP地址,但是考虑到每位博客读者的基础不同,知识贮备有较大差距,所以在这一小部分,简单讲解一下IP地址的分类及用途,在后面程序设计中需要用到这个E类IP地址。

        IP地址 = 网络号 + 主机号

        网络号:指的是不同的网络

        主机号:指的是同一个网段下用来识别不同的主机。那也就是说,主机号所占的位数越多,在该网段下的主机数越多。

A类地址:保留给政府机构使用

        A类IP地址就由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”

        A类地址范围 1.0.0.1 - 126.255.255.254

B类地址:分配给中等规模的公司

        B类IP地址就由2字节的网络地址和2字节主机地址组成,网络地址的最高位必须是“10”。

        B类地址范围 128.0.0.1 - 191.255.255.254

C类地址:分配给任何需要的人

        C类IP地址就由3字节的网络地址和1字节主机地址组成,网络地址的最高位必须是“110”。

        C类地址范围 192.0.0.1 - 223.255.255.254

D类地址:用于组播

        组播地址不同于单播地址,它并不属于特定某个主机,而是属于一组主机。一个组播地址表示一个群组,需要接收组播报文的接收者都加入这个群组。

        D类地址范围 224.0.0.1 - 239.255.255.254

E类地址:用于实验

        E类地址范围 240.0.0.1 - 255.255.255.254

特殊地址:每一个字节都为0的地址(“0.0.0.0”)对应于当前主机; INADDR_ANY —>代表当前主机所有的地址

        127.0.0.1 回环地址 —> 在当前主机内部自动形成闭环的网络 —> 主要用于主机内部不同的应用程序间通信

        如果已经确定当前客户端 和 服务器 都是在同一台主机上运行,那么可以使用本地回环地址

3、组播的特点及应用

(1)、特点

  • 效率高:组播传输的数据包只需要经过一次发送操作,就可以同时传输到多个接收者,可以有效地降低网络传输的负载。
  • 可扩展性:组播支持动态加入和退出组播组,能够自适应地处理组播成员的加入和离开。
  • IP组播地址:在IPv4中,组播使用D类地址(224.0.0.0至239.255.255.255),而在IPv6中,组播地址以ff00::/8开头。这些特殊地址用于标识不同的组播组,使路由器能够识别并正确转发组播报文。
  • 路由协议的支持:为有效管理组播流量,互联网工程任务组(IETF)定义了几种专门的组播路由协议,如PIM(Protocol Independent Multicast)、DVMRP(Distance Vector Multicast Routing Protocol)等,它们帮助确定最有效的路径来分发组播数据。
  • 不可靠性:与普通的UDP一样,组播只提供不可靠的数据传输服务。如果某个接收者没有接收到数据包,发送者不会得到任何提示或反馈信息。

(2)、应用

  • 多媒体流媒体:在局域网或广域网上传输音视频流,快速向多个接收者发送相同的视频和音频数据。
  • 分布式应用的数据分发:实现高效的数据分发,例如在大型集群环境下广播服务的状态信息。
  • 网络游戏:用于多人联机游戏,使多个玩家能够同时收到相同的游戏状态和动作。
  • 网络广播:向多个设备广播事件和消息,例如路由器向所有连接的设备发送网络配置信息。
  • 实时数据更新:用于实时的数据更新,例如在金融行业订阅财经数据的实时更新。

4、组播的通信流程

        组播通信的发送端程序与普通UDP发送端创建流程几乎一致,区别在于,其目标IP地址需要换成D类IP地址。

        组播通信的接收端则是需要在普通UDP接收端程序的基础上,增加一步“加群”的操作,即将当前的IP地址设置到组播地址中

5、组播通信的程序

(1)、组播发送端步骤

①、创建UDP套接字

int socketfd = socket(AF_INET,SOCK_DGRAM,0);

②、发送数据,往组播地址(224.0.0.10 )里面发送数据

struct sockaddr_in sendAddr;//IPV4地址结构体变量 
sendAddr.sin_family = AF_INET; 
sendAddr.sin_port = htons(GROUPPORT); 
sendAddr.sin_addr.s_addr = inet_addr(GROUPADDR);//一定是组播地址 
sendto(socketfd, buf, strlen(buf), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));

③、关闭套接字

close(socketfd);

(2)、组播接收端步骤

①、创建UDP套接字

int socketfd = socket(AF_INET, SOCK_DGRAM, 0);

②、设置组播ip(初始化 组播结构体)

函数原型:
    #include <arpa/inet.h>
    int inet_pton(int af, const char *src, void *dst);//函数原型
函数参数:
    af: 你要选择哪一种协议族  IPV4 --》AF_INET  还是 IPV6--》AF_INET6
    src: 本地IP地址
    dst:将本地IP地址转为网络IP地址存储到这里
函数功能:
    将本地IP地址转为网络IP地址
函数返回值:
    成功返回0, 失败返回-1

//配置方法
struct ip_mreq vmreq;
inet_pton(AF_INET, "224.0.0.10", &vmreq.imr_multiaddr); // 组播地址
inet_pton(AF_INET, "192.168.63.2", &vmreq.imr_interface); // 需要添加到组的ip

③、加入组播属性(设置套接字 可以接收组播信息)

setsockopt(socketfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &vmreq, sizeof(vmreq));

④、绑定地址

struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(atoi(argv[1]));
saddr.sin_addr.s_addr = htonl(INADDR_ANY); //htonl(INADDR_ANY)  代表 主机所有的地址
bind(socketfd, (struct sockaddr *)&saddr, sizeof(saddr));

⑤、接收数据

recvfrom(......)

(3)、组播实现程序

①、组播发送端

#include<stdio.h>
#include <sys/types.h>  
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#define GROUPADDR   "224.0.0.10" //组播地址
#define GROUPPORT   10000

int main()
{
    printf("组播发送端.....\n");
        
    //1、创建UDP数据报套接字
    int socketfd = socket(AF_INET,SOCK_DGRAM,0);
    if(socketfd == -1)
    {
        perror("socket error");
        return -1;
    }
    
    //2、发送数据,往组播地址(224.0.0.10 )里面发送数据
    struct sockaddr_in sendAddr;//IPV4地址结构体变量
    sendAddr.sin_family = AF_INET;
    sendAddr.sin_port = htons(GROUPPORT);
    sendAddr.sin_addr.s_addr = inet_addr(GROUPADDR);//一定是组播地址
    
    while(1)
    {
        char buf[1024]={0};
        printf("data:");
        scanf("%s",buf); 
        sendto(socketfd,buf,strlen(buf),0,( struct sockaddr *)&sendAddr,sizeof(sendAddr));
    }
    
    //3、关闭 
    close(socketfd);
    
    return 0;
}

②、组播接收端

#include<stdio.h>
#include <sys/types.h>     
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#define OWNADDR "192.168.112.109" //接收端的IP地址   当前ubuntu的IP地址
#define GROUPADDR   "224.0.0.10"  //组播地址
#define GROUPPORT   10000

int main()
{
    printf("组播接收端.....\n");
    //1、创建UDP套接字
    int socketfd = socket(AF_INET,SOCK_DGRAM,0);
    if(socketfd == -1)
    {
        perror("socket error");
        return -1;
    }
    
    //2、定义组播结构体
    struct ip_mreq vmreq;
    
    //3、设置组播ip(初始化 组播结构体)
    inet_pton(AF_INET,GROUPADDR,&vmreq.imr_multiaddr); // 组播地址
    inet_pton(AF_INET,OWNADDR,&vmreq.imr_interface); // 需要添加到组的ip
    
    //4)加入组播属性(也就是设置这个套接字 可以接收组播信息)
    setsockopt(socketfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&vmreq,sizeof(vmreq));
    
    //5)绑定地址
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(GROUPPORT);
    saddr.sin_addr.s_addr = htonl(INADDR_ANY); //htonl(INADDR_ANY)  代表 主机所有的地址
    bind(socketfd,(struct sockaddr *)&saddr,sizeof(saddr));
    
    //6)接收数据
    struct sockaddr_in otherAddr;
    int len = sizeof(struct sockaddr_in);
    
    while(1)
    {
        char buf[1024]={0};
        recvfrom(socketfd,buf,sizeof(buf),0, (struct sockaddr *)&otherAddr,&len);
        printf("来自 %s:%u  recv:%s\n",inet_ntoa(otherAddr.sin_addr),ntohs(otherAddr.sin_port),buf);
    }
    
    //关闭 
    close(socketfd);
    
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何确保Spring单例Bean在高并发环境下的安全性?

在Spring中&#xff0c;单例Bean就像是一个“公共的水杯”&#xff0c;整个应用程序中的所有线程都会共享这一个实例。在大部分情况下&#xff0c;这没什么问题&#xff0c;但如果多个线程同时想要修改这个“水杯”里的内容&#xff0c;就可能会出现问题了。 想象一下&#xff…

Jenkins下载 Maven、Allure 插件并且配置环境

文章目录 Jenkins在插件中心下载 maven、allure插件maven插件下载allure插件下载 配置maven、allure 往期推荐&#xff1a; 最新! 在 Linux上搭建Jenkins环境! Jenkins邮件通知的详细配置含邮件通知模板&#xff01; Jenkin配置企业微信通知 Jenkins在插件中心下载 maven、…

ORB-SLAM2源码学习:Initializer.cc⑧: Initializer::CheckRT检验三角化结果

前言 ORB-SLAM2源码学习&#xff1a;Initializer.cc⑦: Initializer::Triangulate特征点对的三角化_cv::svd::compute-CSDN博客 经过上面的三角化我们成功得到了三维点&#xff0c;但是经过三角化成功的三维点并不一定是有效的&#xff0c;需要筛选才能作为初始化地图点。 …

图形化数据报文转换映射工具

目录 概要整体架构流程技术名词解释技术细节小结 概要 在当今数字化时代&#xff0c;数据的处理和分析是企业、科研机构以及各类组织日常运营的核心环节。数据来源广泛&#xff0c;格式多样&#xff0c;常见的数据格式包括XML&#xff08;可扩展标记语言&#xff09;和JSON&a…

[ACTF2020 新生赛]Upload1

题目 以为是前端验证&#xff0c;试了一下PHP传不上去 可以创建一个1.phtml文件。对.phtml文件的解释: 是一个嵌入了PHP脚本的html页面。将以下代码写入该文件中 <script languagephp>eval($_POST[md]);</script><script languagephp>system(cat /flag);&l…

Arduino大师练成手册 -- 读取DS18B20

硬件连接 连接引脚&#xff1a; 将 DS18B20 的 VCC 引脚连接到 Arduino 的 5V 引脚。 将 DS18B20 的 GND 引脚连接到 Arduino 的 GND 引脚。 将 DS18B20 的 DATA 引脚连接到 Arduino 的数字引脚&#xff08;例如 D2&#xff09;。 在 DATA 引脚和 VCC 引脚之间连接一个 4.7…

第十五届蓝桥杯大赛软件赛省赛Java 大学 B 组(1、2题)

1.报数游戏 问题描述 小蓝和朋友们在玩一个报数游戏。由于今年是 2024 年&#xff0c;他们决定要从小到大轮流报出是 20或 24 倍数的正整数。前 10 个被报出的数是&#xff1a;20,24,40,48,60,72,80,96,100,120。请问第 202420242024个被报出的数是多少? 答案提交 这是一道结果…

【优选算法】10----无重复字符的最长子串

---------------------------------------begin--------------------------------------- 题目解析&#xff1a; 看到这一类题目&#xff0c;有没有那种一眼就感觉时要用到滑动窗口的感觉&#xff0c;铁子们&#xff1f; 讲解算法原理&#xff1a; 方法一: 暴力解法&#xff…

Java 高级工程师面试高频题:JVM+Redis+ 并发 + 算法 + 框架

前言 在过 2 个月即将进入 3 月了&#xff0c;然而面对今年的大环境而言&#xff0c;跳槽成功的难度比往年高了很多&#xff0c;很明显的感受就是&#xff1a;对于今年的 java 开发朋友跳槽面试&#xff0c;无论一面还是二面&#xff0c;都开始考验一个 Java 程序员的技术功底…

Vue3.5 企业级管理系统实战(三):页面布局及样式处理 (Scss UnoCSS )

本章主要是关于整体页面布局及样式处理&#xff0c;在进行这一章代码前&#xff0c;先将前两章中的示例代码部分删除&#xff08;如Home.vue、About.vue、counter.ts、App.vue中引用等&#xff09; 1 整体页面布局 页面整体布局构成了产品的框架基础&#xff0c;通常涵盖主导…

Vue平台开发三——项目管理页面

前言 对于多个项目的使用&#xff0c;可能需要进行项目切换管理&#xff0c;所以这里创建一个项目管理页面&#xff0c;登录成功后跳转这个页面&#xff0c;进行选择项目&#xff0c;再进入Home页面展示对应项目的内容。 一、实现效果图预览 二、页面内容 功能1、项目列表展…

WPS计算机二级•幻灯片的基础操作

听说这是目录哦 PPT的正确制作步骤&#x1f6e3;️认识PPT界面布局&#x1f3dc;️PPT基础操作 快捷键&#x1f3de;️制作PPT时 常用的快捷技巧&#x1f3d9;️快速替换PPT的 文本字体&#x1f303;快速替换PPT 指定文本内容&#x1f305;能量站&#x1f61a; PPT的正确制作步…

安装 docker 详解

在平常的开发工作中&#xff0c;我们经常需要部署项目。随着 Docker 容器的出现&#xff0c;大大提高了部署效率。Docker 容器包含了应用程序运行所需的所有依赖&#xff0c;避免了换环境运行问题。可以在短时间内创建、启动和停止容器&#xff0c;大大提高了应用的部署速度&am…

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

BLE透传方案,IoT短距无线通信的“中坚力量”

在物联网&#xff08;IoT&#xff09;短距无线通信生态系统中&#xff0c;低功耗蓝牙&#xff08;BLE&#xff09;数据透传是一种无需任何网络或基础设施即可完成双向通信的技术。其主要通过简单操作串口的方式进行无线数据传输&#xff0c;最高能满足2Mbps的数据传输速率&…

32、【OS】【Nuttx】OSTest分析(1):stdio测试(二)

背景 接上篇wiki 31、【OS】【Nuttx】OSTest分析&#xff08;1&#xff09;&#xff1a;stdio测试&#xff08;一&#xff09; 继续stdio测试的分析&#xff0c;上篇讲到标准IO端口初始化&#xff0c;单从测试内容来说其实很简单&#xff0c;没啥可分析的&#xff0c;但这几篇…

设计新的 Kibana 仪表板布局以支持可折叠部分等

作者&#xff1a;来自 Elastic Teresa Alvarez Soler, Hannah Mudge 及 Nathaniel Reese 在 Kibana 中构建可折叠仪表板部分需要彻底改造嵌入式系统并创建自定义布局引擎。这些更新改进了状态管理、层次结构和性能&#xff0c;同时为新的高级仪表板功能奠定了基础。 我们正在开…

uni-app 程序打包 Android apk、安卓夜神模拟器调试运行

1、打包思路 云端打包方案&#xff08;每天免费次数限制5&#xff0c;最简单&#xff0c;可以先打包尝试一下你的程序打包后是否能用&#xff09;&#xff1a; HBuilderX 发行App-Android云打包 选择Android、使用云端证书、快速安心打包本地打包&#xff1a; HBuilderX …

Jetpack Compose 和 Compose Multiplatform 还有 KMP 的关系

今天刚好看到官方发布了一篇文章&#xff0c;用于讨论 Compose Multiplatform 和 Jetpack Compose 之间的区别&#xff0c;突然想起之前评论区经常看到说 “Flutter 和 CMP 对于 Google 来说项目重叠的问题”&#xff0c;刚好可以放一起聊一聊。 最近写的几篇内容写的太干&…

第38周:猫狗识别 (Tensorflow实战第八周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 输出 二、数据预处理 2.1 加载数据 2.2 再次检查数据 2.3 配置数据集 2.4 可视化数据 三、构建VGG-16网络 3.1 VGG-16网络介绍 3.2 搭建VGG-16模型 四、编译 五、训练模型 六、模型评估 七、预测 总结 前言…