建设网站需要的资源/手机优化大师官方版
UDP特性之组播
- 1. 组播的特点
- 2. 设置主播属性
- 2.1 发送端
- 2.2 接收端
- 3. 组播通信流程
- 3.1 发送端
- 3.2 接收端
- 4. 通信代码
原文链接
在公司测试广播和多播有一点问题。。。
1. 组播的特点
组播也可以称之为多播这也是UDP的特性之一。组播是主机间一对多的通讯模式,是一种允许一个或多个组播源发送同一报文到多个接收者的技术。组播源将一份报文发送到特定的组播地址,组播地址不同于单播地址,它并不属于特定某个主机,而是属于一组主机。一个组播地址表示一个群组,需要接收组播报文的接收者都加入这个群组。
- 广播只能在局域网访问内使用,组播既可以在局域网中使用,也可以用于广域网
- 在发送广播消息的时候,连接到局域网的客户端不管想不想都会接收到广播数据,组播可以控制发送端的消息能够被哪些接收端接收,更灵活和人性化。
- 广播使用的是广播地址,组播需要使用组播地址。
- 广播和组播属性默认都是关闭的,如果使用需要通过setsockopt()函数进行设置。
组播需要使用组播地址,在 IPv4 中它的范围从 224.0.0.0 到 239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三类:
组播地址不属于任何服务器或个人,它有点类似一个微信群号,任何成员(组播源)往微信群(组播IP)发送消息(组播数据),这个群里的成员(组播接收者)都会接收到此消息。
2. 设置主播属性
如果使用组播进行数据的传输,不管是消息发送端还是接收端,都需要进行相关的属性设置,设置函数使用的是同一个,即:setsockopt()。
2.1 发送端
发送组播消息的一端需要设置组播属性,具体的设置方式如下:
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
-
参数:
-
sockfd:用于UDP通信的套接字
-
level:套接字级别,设置组播属性需要将该参数指定为:IPPTOTO_IP
-
optname: 套接字选项名,设置组播属性需要将该参数指定为:IP_MULTICAST_IF
-
optval:设置组播属性,这个指针需要指向一个struct in_addr{} 类型的结构体地址,这个结构体地址用于存储组播地址,并且组播IP地址的存储方式是大端的。
-
optlen:optval指针指向的内存大小,即:sizeof(struct in_addr)
-
struct in_addr
{in_addr_t s_addr; // unsigned int
};
- 返回值:函数调用成功返回0,调用失败返回-1
2.2 接收端
因为一个组播地址表示一个群组,所以需要接收组播报文的接收者都加入这个群组,和想要接收群消息就必须要先入群是一个道理。加入到这个组播群组的方式如下:
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
-
参数:
-
sockfd:基于udp的通信的套接字
-
level:套接字级别,加入到多播组该参数需要指定为:IPPTOTO_IP
-
optname:套接字选项名,加入到多播组该参数需要指定为:IP_ADD_MEMBERSHIP
-
optval:加入到多播组,这个指针应该指向一个struct ip_mreqn{}类型的结构体地址
-
optlen:optval指向的内存大小,即:sizeof(struct ip_mreqn)
-
typedef unsigned int uint32_t;
typedef uint32_t in_addr_t;
struct sockaddr_in addr;struct in_addr
{in_addr_t s_addr; // unsigned int
};struct ip_mreqn
{struct in_addr imr_multiaddr; // 组播地址/多播地址struct in_addr imr_address; // 本地地址int imr_ifindex; // 网卡的编号, 每个网卡都有一个编号
};
// 必须通过网卡名字才能得到网卡的编号: 可以通过 ifconfig 命令查看网卡名字
#include <net/if.h>
// 将网卡名转换为网卡的编号, 参数是网卡的名字, 比如: "ens33"
// 返回值就是网卡的编号
unsigned int if_nametoindex(const char *ifname);
3. 组播通信流程
发送组播消息的一端需要将数据发送到组播地址和固定的端口上,想要接收组播消息的终端需要绑定对应的固定端口然后加入到组播的群组,最终就可以实现数据的共享。
3.1 发送端
- 创建通信的套接字
// 第二个参数是 SOCK_DGRAM, 第三个参数0表示使用报式协议中的udp
int fd = socket(AF_INET, SOCK_DGRAM, 0);
- 主动发送数据的一端不需要手动绑定端口(自动随机分配就可以了),设置UDP组播属性
// 设置组播属性
struct in_addr opt;
// 将组播地址初始化到这个结构体成员中
inet_pton(AF_INET, "239.0.1.10", &opt.s_addr);
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));
- 使用组播地址发送组播消息到固定的端口(接收端需要绑定这个端口)
sendto();
- 关闭套接字(文件描述符)
close(fd);
3.2 接收端
- 创建通信的套接字
// 第二个参数是 SOCK_DGRAM, 第三个参数0表示使用报式协议中的udp
int fd = socket(AF_INET, SOCK_DGRAM, 0);
- 绑定固定的端口,发送端应该将数据发送到接收端绑定的端口上
bind();
- 加入到组播的群组中,入群之后就可以接受组播消息了。
// 加入到多播组
struct ip_mreqn opt;
// 要加入到哪个多播组, 通过组播地址来区分
inet_pton(AF_INET, "239.0.1.10", &opt.imr_multiaddr.s_addr);
opt.imr_address.s_addr = INADDR_ANY;
opt.imr_ifindex = if_nametoindex("ens33");
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));
- 接收组播数据
recvfrom();
- 关闭套接字(文件描述符)
close(fd);
4. 通信代码
发送端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>int main()
{// 1. 创建通信的套接字int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd == -1){perror("socket");exit(0);}// 2. 设置组播属性struct in_addr opt;// 将组播地址初始化到这个结构体成员中即可inet_pton(AF_INET, "239.0.1.10", &opt.s_addr);setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));char buf[1024];struct sockaddr_in cliaddr;int len = sizeof(cliaddr);cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(9999); // 接收端需要绑定9999端口// 发送组播消息, 需要使用组播地址, 和设置组播属性使用的组播地址一致就可以inet_pton(AF_INET, "239.0.1.10", &cliaddr.sin_addr.s_addr);// 3. 通信int num = 0;while(1){sprintf(buf, "hello, client...%d\n", num++);// 数据广播sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&cliaddr, len);printf("发送的组播的数据: %s\n", buf);sleep(1);}close(fd);return 0;
}
注意事项:在组播数据的发送端,需要先设置组播属性,发送的数据是通过sendto()函数发送到某一个组播地址上,并且在程序中数据发送到了接收端的9999端口,因此接收端程序必须要绑定这个端口才能收到组播消息。
接收端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>int main()
{// 1. 创建通信的套接字int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd == -1){perror("socket");exit(0);}// 2. 通信的套接字和本地的IP与端口绑定struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999); // 大端addr.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));if(ret == -1){perror("bind");exit(0);}// 3. 加入到多播组struct ip_mreqn opt;// 要加入到哪个多播组, 通过组播地址来区分inet_pton(AF_INET, "239.0.1.10", &opt.imr_multiaddr.s_addr);opt.imr_address.s_addr = INADDR_ANY;opt.imr_ifindex = if_nametoindex("ens33"); // enp0s3setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));char buf[1024];// 3. 通信while(1){// 接收广播消息memset(buf, 0, sizeof(buf));// 阻塞等待数据达到recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);printf("接收到的组播消息: %s\n", buf);}close(fd);return 0;
}
注意事项:作为组播消息的接收端,必须要先绑定一个固定端口(发送端就可以把数据发送到这个固定的端口上了),然后加入到组播的群组中(一个组播地址可以看做是一个群组),这样就可以接收到组播消息了。
相关文章:

UDP特性之组播(多播)
UDP特性之组播 1. 组播的特点2. 设置主播属性2.1 发送端2.2 接收端 3. 组播通信流程3.1 发送端3.2 接收端 4. 通信代码 原文链接 在公司测试广播和多播有一点问题。。。 1. 组播的特点 组播也可以称之为多播这也是UDP的特性之一。组播是主机间一对多的通讯模式,是…...

ElasticSearch之cat shards API
命令样例如下: curl -X GET "https://localhost:9200/_cat/shards?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下: index shard prirep state docs s…...

Thread-Per-Message设计模式
Thread-Per-Message是为每一个消息的处理开辟一个线程,以并发方式处理,提高系统整体的吞吐量。这种模式再日常开发中非常常见,为了避免线程的频繁创建和销毁,可以使用线程池来代替。 示例代码如下: public class Requ…...

运筹学经典问题(一):指派问题
问题描述 有 N N N个任务,需要 N N N个人去完成,每个人完成不同工作的效率不同(或者资源、收益等等),需要怎么分配使得整体的效率最高(成本最低等等)呢?这就是经典的指派问题啦&…...

产品经理之如何编写竞品分析(医疗HIS系统管理详细案例模板)
目录 一.项目周期 二.竞品分析的目的 三.竞品分析包含的维度 四.如何选择竞品 五.竞品画布 六.案例模板 一.项目周期 在整个项目的周期,产品经理所做的事情主要在项目前期做市场分析、需求调研等,下面一张图概况了整个项目周期产品经理、开发工程师…...

虚拟内存管理
虚拟内存管理 页面置换算法 功能和目标: 功能:当缺页中断发生,需要调入新的页面而内存已经满时,选择内存当中哪个物理页面被置换。目标:尽可能的减少页面的换进换出次数(即缺页中断的次数)。具…...

ssh时怎么同时指定其端口号,以及scp文件到远程的指定端口
如果想要通过 SSH 连接到指定端口的远程服务器,可以在 SSH 命令中使用 -p 或 --port 参数来指定端口号。以下是相应的用法: $ ssh -p <port> userhost其中, 是要连接的端口号,user 是远程服务器上的用户名,host…...

Redis过期淘汰策略
一. Redis过期淘汰策略 当Redis已用内存超过maxmemory限定时,触发主动清理策略。 主动清理策略在Redis 4.0之前一共实现了 6 种内存淘汰策略,在 4.0 之后,又增加了 2 种 策略,总共8种: 针对设置了过期时间的key做处理…...

微信小程序---自定义组件
目录 1.局部引用组件 2.全局引用组件 3.组件和页面的区别 4.自定义组件样式 5.properties属性 6.data和properties的区别 7.数据监听器 8.纯数据字段 9.自定义组件-组件的生命周期 lifetimes节点 10.组件所在的页面的生命周期 pageLifetimes节点 11.插槽 &#x…...

CGAL的最优传输曲线重构
1、介绍 此程序包实现了一种重建和简化二维点集的方法。输入是一组具有质量属性的二维点,可能受到噪声和离群值的干扰。输出是一组线段和孤立点,它们近似于输入点,如下图所示。质量属性与每个点的近似重要性有关。 左:输入点集受到…...

使用Docker本地安装部署Draw.io绘图工具并实现远程访问协作办公
前言 提到流程图,大家第一时间可能会想到Visio,不可否认,VIsio确实是功能强大,但是软件为收费,并且因为其功能强大,导致安装需要很多的系统内存,并且是不可跨平台使用。所以,今天给…...

流程图、泳道图的介绍和示例分享,以及自定义元件库的介绍
目录 一. 流程图介绍 二. Processon使用 新建一个流程图 图形的使用 三. 流程图示例 登录界面 门诊业务流程图 住院业务流程图 药房业务流程图 会议OA流程图 四. 泳道图介绍 五. 自定义元件库 5.1 新建一个元件库 5.2 创建元件 5.3 使用自定义元件库 一. 流程图介…...

RabbitMq的详细使用
消息队列RabbitMQ详细使用 文章目录 消息队列RabbitMQ详细使用MQ 的相关概念什么是MQ为什么要用MQMQ 的分类MQ 的选择 RabbitMQRabbitMQ 的概念四大核心概念各个名词介绍安装RabbitMQWeb管理界面及授权操作Docker 安装Hello world简单示例 Work Queues轮训分发消息消息应答自动…...

软件设计师——软件工程(二)
📑前言 本文主要是【软件工程】——软件设计师——软件工程的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 🌄…...

阿里云RDS MySQL 数据如何快速同步到 ClickHouse
云数据库 RDS MySQL 和 云数据库 ClickHouse 是阿里云推出的两个备受欢迎的数据库解决方案,它们为用户提供了可靠的数据存储方案、分析数仓方案,本文介绍如何快速将 RDS MySQL 的数据同步到云数据库 ClickHouse。 如何快速将RDSMySQL的数据同步到云数据库…...

HINet技术要点
《HINet: Half Instance Normalization Network for Image Restoration》发表于CVPR2021,是旷视科技&复旦大学&北大在图像复原方面的的最新进展,所提方案取得了NTIRE2021图像去模糊Track2赛道冠军。 下面谈谈该文章的主要技术点。 1. HIN&#…...

IntelliJ IDEA2023学习教程
详细介绍idea开发工具及使用技巧 1. 2023版安装1.1删除老版本1.2 下载及安装 3.快捷技巧4. 创建各种model 1. 2023版安装 1.1删除老版本 如果以前装有idea需要先删除,以避免冲突,在idea安装目录/bin/Uninstall.exe双击1.2 下载及安装 最新版本 https:/…...

MATLAB基础应用精讲-【数模应用】神经网络(补充篇)
目录 前言 几个相关概念 反向传播 梯度下降 损失函数 优化函数...

洛谷题单【算法1-7】搜索
P1135 奇怪的电梯 一开始以为深搜肯定没问题,从a点出发,衍生出一个二叉树,遍历所有情况就好了,但是会重复,所以加了一个vis防止重复,但是只拿了64pts,因为有可能某个点并不是最短被到达的&…...

WordPress主题Lolimeow v8.0.1二次元风格支持erphpdown付费下载
WordPress国人原创动漫主题lolimeow免费下载 lolimeow是一款WordPress国人原创主题,风格属于二次元、动漫、可爱萝莉风,带有后台设置,支持会员中心。该主题为免费主题。 1.侧栏/无侧栏切换! 2.会员中心(配套Erphpdown…...

WTN6xxx系列OTP语音芯片:智能语音解决方案的可靠之选
在智能语音交互领域,唯创知音的WTN6xxx系列OTP语音芯片以其独特的特性成为声音播放提示IC的可靠之选。本文将深入探讨WTN6xxx系列OTP语音芯片的应用优势,展示其在各个方面的卓越性能。 一、低成本、高性能 1.经济实惠: WTN6xxx系列OTP语音芯…...

腾讯云Elasticsearch Service产品体验
基本介绍 产品概述 腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需…...

SQLE 3.0 部署实践
来自 1024 活动的投稿系列 第一篇《SQLE 3.0 部署实践》 . 作者:张昇,河北东软软件有限公司高级软件工程师,腾讯云社区作者。 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。 本文共 32…...

爬虫的分类
爬虫的分类 网络爬虫按照系统结构和实现技术,大致可分为4类,即通用网络爬虫、聚焦网络爬虫、增量网络爬虫和深层次网络爬虫。 1.通用网络爬虫:搜索引擎的爬虫 比如用户在百度搜索引擎上检索对应关键词时,百度将对关键词进行分析…...

简说vue-router原理
vue-router原理 hash模式 实现原理 改变描点监听描点变化 history模式 实现原理 改变url监听url变化 abstracthash 和 history 模式有什么区别? url 不一样原理不同 其他总结扩展 history 出现404错误 vue-router原理 vue-router是vue项目的重要组成部分&#x…...

什么是 Spring 框架?
Spring 框架是一个开源的、轻量级的企业级应用框架,用于构建 Java 应用程序。它提供了全面的基础设施支持,以简化企业级应用的开发。Spring 的核心目标是通过促进良好的设计原则和编程习惯来提高 Java 开发人员的效率和系统的可维护性。 Spring 框架的主…...

Vue2.x源码:new Vue()做了啥
例子1new Vue做了啥?new Vue做了啥,源码解析 initMixin函数 初始化 – 初始化Vue实例的配置initLifecycle函数 – 初始化生命周期钩子函数initEvents – 初始化事件系统初始化渲染 initRender初始化inject选项 例子1 <div id"app"><div class"home&…...

iOS 借助DSYMTools工具定位到闪退的具体行数和方法名
1、下载 dSYMTools-master 工具,下载安装后,如下图: 2、通过Bugly或友盟等异常记录工具,找到闪退的内存地址和偏移量信息上图是Bugy记录的闪退信息,友盟的参考如下: 关于工具的原理和其他描述,…...

分布式解决方案与实战
分布式多线程性能调优 使用多线程优化接口 //下单业务public Object order( long userId){long start System.currentTimeMillis();//方法的开始时间戳(ms)JSONObject orderInfo remoteService.createOrder(userId);Callable<JSONObject> calla…...

GitHub入门介绍
GitHub是一个基于web的版本控制系统,主要用于代码管理和协作开发。它是开源的,并且提供了一系列的功能,方便开发人员进行版本控制、代码托管和团队协作。 以下是GitHub的一些基本概念和功能: 版本控制:GitHub使用Git作…...