linux下UDP组播接收不到数据的说明

linux下加入组播组收不到组播信息问题排查 linux下收不到组播数据,发不出igmp报文 阅读详情
AI摘要

本文介绍了一种基于libuv的跨平台组播数据接收方法。针对Windows与Linux平台的差异,详细阐述了如何通过调整组播地址绑定策略来确保程序在不同操作系统上都能正常工作。

背景

在一个跨平台的桌面项目中,由于涉及多线程中对象的创建、销毁等,基于QT的对象绑定机制(QObject子类)来做实现时,需要相当心累的设计,才能避免跨线程的异常。由于QT的这个天然机制,在实现很多业务(非界面)模块时,都避免了基于QObject。网络模块中的UDP等功能,同样的也未基于QUdpSocket及其相关,而是包装了libuv(尽管,对桌面来说libuv也需要再折腾,但libuv作者已经明示了这个点了)

 

现象

基于libuv的程序示例,在windows下,可以正常工作(接收到组播数据),但是,同样的代码,在linux下无法接收到组播数据。

大概的实现流程是:按照libuv的官方说明(初始化sockaddr结构、udp操作),使用uv_ip4_addr、uv_udp_init、uv_udp_bind、uv_udp_set_membership等接口,很快就实现了一个可接收组播的原型,大概如下:

uv_udp_t* udpHandle = new uv_udp_t;
sockaddr_in addr;
int iRet = -1;
std::string localIP = "192.168.2.102";	// 本机的某个网卡的IP
std::string multicastIP = "224.1.1.8";	// 加入的组播IP,以接收数据
int localPort = 15909;
iRet = ::uv_ip4_addr(localIP.c_str(), localPort, &addr);
iRet = ::uv_udp_init(objLoop, udpHandle);
iRet = ::uv_udp_bind(udpHandle, (const sockaddr*)&addr, UV_UDP_REUSEADDR);
iRet = ::uv_udp_set_membership(udpHandle, multicastIP.c_str(),
							   localIP.c_str(), UV_JOIN_GROUP);

分析

由于linux组播实操经历的缺失,先期主要是搜看各类文章:有些文章,直接采用了修改路由等各种配置解决;有些文章,也采用了linux下绑定0.0.0.0即any的方式来接所有;另外一些,也说明了linux下与windows中组播的区别(但是,并没有适当的关键字以方便大家的搜索)。

最终,还是又继续翻看了UNIX网络编程(中文 第3版)的第21章。其中直接有关的是:

21.9节开始的模糊不清的文字说明,以及图21-14的代码示例(2、12-17行),还有sap.mcast.net对应着(224.2.127.254);

21.10节,这段话“我们想要给接收套接字捆绑多播组和端口,譬如说239.255.1.2端口8888。(回顾一下,我们可以只捆绑通配IP地址和端口8888,不过还是捆绑多播地址以防止目的端口同为8888的其他数据报到达本套接字)”(无论允许与否,我都想吐槽一下的:这种不加标点的长句子,是在锻炼国码奴的堆栈能力吧)。下面是英文版书中的对应文字(反倒是直观了):

We want the receiving socket to bind the multicast group and port, say 239.255.1.2 port 8888. (Recall that we could just bind the wildcard IP address and port 8888, but binding the multicast address prevents the socket from receiving any other datagrams that might arrive destined for port 8888.)

 

与本问题,间接有关的是,第21.2、21.3小节的原理性说明。

由以上,在linux下接收组播数据时,终于可以舒适安心的采用先绑定组播IP的方式进行实现了。

 

方案

1、基于libuv的方案示例

uv_udp_t* udpHandle = new uv_udp_t;
sockaddr_in addr;
int iRet = -1;
std::string localIP = "192.168.2.102";	// 本机的某个网卡的IP
std::string multicastIP = "224.1.1.8";	// 加入的组播IP,以接收数据
int localPort = 15909;

#if defined(_WIN32)
iRet = ::uv_ip4_addr(localIP.c_str(), localPort, &addr);
#else
// 下面是linux下,与windows的不同点
iRet = ::uv_ip4_addr(multicastIP.c_str(), localPort, &addr);	
#endif

// 以下是通用的
iRet = ::uv_udp_init(libuvLoop, udpHandle);
iRet = ::uv_udp_bind(udpHandle, (const sockaddr*)&addr, UV_UDP_REUSEADDR);
iRet = ::uv_udp_set_membership(udpHandle, multicastIP.c_str(),
							   localIP.c_str(), UV_JOIN_GROUP);

2、使用原生实现的方案示例

可能你在项目中,并不使用libuv,因此,本文也给出一个大概的示例

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

sockaddr_in addr;
int iRet = -1;
std::string localIP = "192.168.2.102";	// 本机的某个网卡的IP
std::string multicastIP = "224.1.1.8";	// 加入的组播IP,以接收数据
int localPort = 15909;

addr.sin_family = AF_INET;
addr.sin_port = htons(localRecvPort);				// 本地想接收的端口

#if defined(_WIN32)
addr.sin_addr.s_addr = inet_addr(localIP.c_str());	// 本机的某个网卡的IP
#else
// 下面是linux下,与windows的不同点
// linux加入组播时,本机需绑定0.0.0.0或者组播地址
addr.sin_addr.s_addr = inet_addr(multicastIP.c_str());	
#endif

bind(udpSocket, (sockaddr *)&saddr, sizeof(addr));
int reuseOn = 1;
setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
ip_mreq mreq;  
mreq.imr_multiaddr.s_addr = inet_addr(multicastIP.c_str());  
mreq.imr_interface.s_addr = inet_addr(localIP.c_str());  
setsockopt(udpSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

 

相关文章

https://blog.youkuaiyun.com/rcfalcon/article/details/35221759

https://blog.youkuaiyun.com/xqligong/article/details/106124408

https://stackoverflow.com/questions/32824029/upnp-bind-with-multicast

https://www.cnblogs.com/lifan3a/articles/6780760.html

https://blog.youkuaiyun.com/qing310820/article/details/103408235

linux多网卡udp组播收不到数,多网卡的情况下收udp组播数据的坑 多网卡指定其中一个网卡收udp组播的三个关键(缺一不可):1. 接收udp组播的网卡的ip,必须设置成抓包看到的组播发送ip的同一网段的ip.2. 代码里本地监听地址ip必须是0.0.0.0, 端口是组播端口.(如下代码搜搜"关键")3. 代码加入组播的set里需要指定收组播的网卡ip. (如下代码搜搜"关键")此外也需要看iptables和防火墙有没有限制。。。1.看防火墙有没有关闭:$ sud... 阅读详情

相关推荐

【Qt】QLocalSocket与QLocalServer问题:接收不到数据、只能收到第一条、数据不完整解决方案【2023.05.24】

Qt很强大,但是Qt的帮助文档、API属实是让我们走不少弯路。QLocalSocket一个很简单的东西,我仅想用来实现一个简单的本地进程通信,就遇到了:客户端循环发送数据,服务端只能接收到一条、接收到数据不完整等奇奇怪怪的现象。

qq_25231249的博客 2412

Linux:无法接收组播数据

Linux:无法接收组播数据

hhd1988的专栏 4644

第四章 Linux套接字通信:12.UDP特性之组播(多播)

组播也可以称之为多播这也是UDP的特性之一

qq_62848032的博客 1404

Linux无法接收组播

1、检查Linux系统是否接收到组播数据 使用tcpdump工具,检查源或者目的地址239.1.1.1:9001的数据包 tcpdump -i ens33 host 239.1.1.1 port 9001 2、关闭防火墙 暂时关闭: systemctl stop firewalld service iptables stop 永久关闭: systemctl disable firewalld chkconfig iptables off 3、添加组播地址路由: route add -net 239.1.1.

goodcrony的博客 1万+

【Linux进阶】SO_REUSEPORT实现UDP组播

组播报文的目的地址使用D类IP地址, D类地址不能出现在IP报文的源IP地址字段。单播数据传输过程中,一个数据包传输的路径是从源地址路由到目的地址,利用“逐跳”的原理在IP网络中传输。

W1024201的博客 1260

DAIC-WOZ抑郁数据集实战:从申请到特征提取的全流程避坑指南

本文详细解析了DAIC-WOZ抑郁数据集从申请到特征提取的全流程,提供了实用的避坑指南和代码模板。涵盖数据获取技巧、多模态特征工程(面部动作单元、音频特征、文本处理)以及样本不平衡解决方案,帮助研究者高效处理这一经典抑郁分析数据集。

weixin_29196315的博客 172

UDP组播

终于搞明白了UDP组播,5分钟讲解清楚。

weixin_28673511的博客 7232

ITK-snap进行分割区域标注、三维显示及改变显示颜色

在进行医学图像器官分割时,无论我们是用传统方法还是深度学习,最后肯定要用到手动分割的区域作为金标准来验证我们方法的精度。但是手动标注器官的轮廓是十分耗时的,这里我介绍一个比较简单的标注方法,以肺分割作为例子。 我们使用ITK-snap作为分割标注工具。 当切片间距离比较小时,比如1mm,一个患者的完整HRCT序列通常在200张以上,如果让医生一一进行分割区域标注是非常耗时乏味的。因此,我们可以使用最简单的阈值法比如OSTU,加上基本的形态学操作对肺进行粗分割得到粗略的分割掩码,在此基础上再手动的对分割结果进

u010409517的博客 2万+

Linux C编程 socket——Udp组播(多播)

Linux C编程 socket——Udp组播(多播)Udp多播简介概述组播应用组播地址组播地址与MAC地址的映射Udp组播编程函数简介UDP组播示例 Udp多播简介 概述 单播用于两个主机间单对单的通信 广播用于一个主机对整个局域网上所有主机上的数据通信 单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网的主机进行通信 实际情况下,经常需要对一组特定的主机进行通信,而不是所有局域网...

weixin_43790540的博客 9895

uniapp+萤石视频监控实战:解决ezuikit.js真机调试不显示的5个关键步骤

本文针对Uniapp集成萤石视频监控时ezuikit.js在真机调试中黑屏不显示的问题,提供了5个关键解决步骤。核心方案是采用Webview加载独立H5播放页,以规避跨平台环境差异,并详细阐述了资源放置、多端适配、通信处理及系统化排查方法,确保视频流稳定播放。

weixin_29001655的博客 287

手把手教你学Simulink——基于经典PID控制的电机系统场景实例:永磁同步电机(PMSM) PID转速控制仿真

*永磁同步电机(PMSM)因其高效、高功率密度和良好的动态响应特性,在现代工业自动化、电动汽车驱动系统等领域得到了广泛应用。为了实现对PMSM的速度精确控制,通常采用矢量控制(Field Oriented Control, FOC)**策略,其中PID控制器是实现速度环和电流环调节的关键组件。本教程将带你使用构建一个基于PID控制的永磁同步电机转速控制系统仿真模型PMSM电机建模矢量控制(FOC)策略实现PID控制器设计系统仿真与调试控制效果分析本文介绍了如何使用构建一个。

MHD0815的博客 6952

Linux网络编程系列之UDP组播

Linux网络编程系列之UDP组播,UDP组播的简单介绍和使用

AABond的博客 4507

华为OD机试双机位C卷-恢复数字序列 (Py/Java/C/C++/Js/Go)

华为OD机试双机位C卷 恢复数字序列,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 恢复数字序列。

qq_45776114的博客 1203

网络编程 | UDP组播通信

组播是介于单播与广播之间,在一个局域网内,将某些主机添加到组中,并设置一个组地址。将数据发送到组播地址时,加入到该组的所有主机都能接收到数据。组播是主机间一对多的通信模式, 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。类似于生活中较为常见的群聊功能,在群内的所有群员,都可以在群内发送消息给群友,也可以接收到来自任意群友的消息。

weixin_49337111的博客 2593

petalinux2022.2启动文件编译配置

petalinux2021之前的版本里,导入目录components/yocto/下的“environment-setup-aarch64-xilinx-linux” 和 “layers/core/oe-init-build-env”的环境,能使用Yocto的devtool工具。(加入下面内容,先petalinux-build下载完成后才能有源码)制作 BOOT.BIN 启动文件:petalinux-package --boot --fsbl --fpga --u-boot --force。

wangjie36的博客 1391

Jetson agx Orin 适配Xenomai4

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。

xiaoning132的专栏 466

Linux网络编程-UDP组播服务客户端代码实现

目录 一、UDP组播介绍 1.UDP介绍 2.UDP组播 3.组播地址 4.组播的原理: 二、UDP组播编程 1.UDP组播的基本步骤 2.加入组播组-setsockopt 三、UDP组播服务端代码实现 1.代码实现 2.运行结果 四、UDP单播客户端代码实现 1.代码实现 2.运行结果 一、UDP组播介绍 1.UDP介绍 UDP协议进行信息的传输之前不需要建议连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服...

ProYuan的博客 4729

【人工智能】 WebDev Arena:实时AI Web开发竞赛的技术探索与价值

《AI编程竞赛推动Web开发技术创新》摘要:WebDev Arena作为聚焦Web开发领域的实时AI编程竞赛,通过标准化竞技环境检验AI模型在代码生成、问题解决等方面的能力。竞赛覆盖前端、后端等全流程开发环节,采用实时评分机制,推动AI对复杂Web需求的理解和多元技术栈适配。该赛事不仅促进AI编程技术创新,更为Web开发行业与AI技术融合搭建桥梁,有望提升开发效率、降低技术门槛。未来将拓展Web3.0等前沿技术主题,持续推动行业智能化发展。(150字)

奶爸的编程之路,也就一周冷个三天 256

linux udp组播收不到数据包,组播收不到数据

void udpclient(int argc, char **argv){int myFd, clientFd;struct sockaddr_in myAddr, clientAddr;struct ip_mreq mreq;int addrlen = sizeof(clientAddr);char buf[MAXBUF];char addrTemp[INET_ADDRSTRLEN];int ...

weixin_42139357的博客 2391

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Linux | 组播接收转发

……

u013669912的博客 1037

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

跨平台的组播测试工具mping、udp_sender及udp_reciver的源码及使用教程

UDP组播测试对于局域网内数据链路测试十分必要,轻量化和易用性是首要考虑的问题,使用mping作为UDP组播测试工具,能够非常方便的进行linux、Windows等平台的组播测试。本文第4章还提供了基于C/C++的udp_sender和udp_reciver组播源码,可以在Linux下编译执行。

驯龙高手_追风的博客 4327

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

udp组播示例(发送、接收)

原因不多说,目录结构扁平, data.h如下: #pragma once #include <cstring> #include <cstdint> #include <sys/types.h> #define MULTICAST_IP "234.0.0.1" #define MULTICAST_PORT 28928 #pragma pack(1) typedef struct price { int64_t mantissa; int64_

哦,原来你也在这里。 2977

关于QT中UDP套接字和组播简单说明

关于QT中UDP套接字和组播简单说明 关于linux的UDP传输: 关于QT的UDP传输: 与TCP不同的是, TCP的服务端套接字需要通信套接字和监听套接字, 客户端需要通信套接字, 而在UDP中, 双方只需要UDP套接字, 也就是一个通信套接字即可. UDP服务端的QUdpSocket对象只需用**.bind()绑定端口, 然后客户端就可以用writeDatagram(str, ip, p...

tofu的博客 2174

组播接收工具 linux,在Linux上使用python接收组播UDP数据报

我有一个硬件设备在我的网络上发送多播数据。我写了一个接收数据并打印它的python脚本。但是,我发现它只能在我的Windows XP PC上运行,并且在我的Ubuntu Linux 10.04 PC上无法运行。在Linux下,没有收到任何东西。它只是围绕while循环,并没有收到任何数据。我的代码发布在下面。你能看出为什么这在Linux下无法正常工作吗?谢谢,Rab。在Linux上使用python...

weixin_30583711的博客 810

linux下怎么使用C语言编写接收和发送udp组播数据?

一,发送端 代码如下: 先调用initUdpMultiCastSender初始化,   int initUdpMultiCastSender(uint32_t localip,uint16_t localport) { int sockfd = socket(AF_INET,SOCK_DGRAM,0); if (-1 == sockfd) { printf("[initUdpM...

yuhengyue的博客 8056
上一篇: std::mutex的使用备忘
下一篇: QT5 “Multicast Receiver Example”组播接收数据的说明
smartcore
博客等级 码龄19年 30粉丝 47原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值