当前位置: 首页 > news >正文

Qt低版本多网卡组播bug

原文地址

最近在某个项目中,发现了一个低版本Qt的bug,导致组播无法正常使用,经过一番排查,终于找到了原因,特此记录。

环境

  • Qt:5.7.0 mingw32
  • 操作系统:windows 11

现象

在Qt5.7.0版本中,使用组播发送数据时,发现数据无法接收,经过长时间的排查,发现是Qt的bug,具体现象如下:

  1. 在Qt5.7.0版本中,使用组播发送数据时,发现数据无法接收。
  2. 使用串口调试工具,发现发送的数据包没有问题(无论何种情况都可以)。
  3. 使用wireshark抓包,发现发送的数据包没有问题。
  4. 使用Qt自带的组播收发例子,本机测试发现可以正常接收数据,但是当收发处于两台电脑时不能接收。

排查步骤

  1. 使用调试工具

    • 使用地址 0.0.0.0: port 不能接收到数据
    • 使用地址 192.168.1.100: port 可以接收到数据
    • 使用地址 239.255.255.255: port 不能接收到数据
  2. 测试自带的组播收发例子

    • 本机测试可以正常接收数据
    • 两台电脑测试不能接收数据

尝试解决

经过一顿搜索,加上长时间的摸索(本机的虚拟网卡太多),长时间折腾后发现只有一个网卡的时候可以正常。必须祭出终极大杀器 socket sdk 如果还不行都不知道该怎么办了,结果测试竟然可行


#include <stdio.h>  
#include <winsock2.h>  
#include <ws2tcpip.h>  
#pragma comment(lib, "ws2_32.lib")void sendData(SOCKET sock)
{struct sockaddr_in dest_addr; // 目标地址结构体// 设置目标地址memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.sin_family = AF_INET; // IPv4dest_addr.sin_port = htons(groupPort); // 目标端口号dest_addr.sin_addr.s_addr = inet_addr(groupIp); // 目标IP地址char *sendData = "hello world";sendto(sock, sendData, strlen(sendData), 0, (const struct sockaddr *)&dest_addr, sizeof(dest_addr));
}int main(int argc, char* argv[])
{unsigned short groupPort = 37080;char *bindIp = "192.168.8.112";char *localIp = "192.168.8.112";char *groupIp = "239.255.255.250";printf("%s\n%s\n%s\n%d\n", bindIp, localIp, groupIp, groupPort);if(argc >= 5){bindIp = argv[1];localIp = argv[2];groupIp = argv[3];groupPort = atoi(argv[4]);}int iRet = 0;WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.S_un.S_addr = inet_addr(bindIp);//INADDR_ANY;//addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addr.sin_port = htons(groupPort);bool bOptval = true;iRet = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptval, sizeof(bOptval));if (iRet != 0) {printf("setsockopt fail:%d", WSAGetLastError());return -1;}iRet = bind(sock, (sockaddr*)&addr, sizeof(addr));if (iRet != 0) {printf("bind fail:%d\n", WSAGetLastError());return -1;}printf("socket:%d bind success\n", sock);ip_mreq multiCast;multiCast.imr_interface.S_un.S_addr = inet_addr(localIp);multiCast.imr_multiaddr.S_un.S_addr = inet_addr(groupIp);iRet = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multiCast, sizeof(multiCast));if (iRet != 0) {printf("setsockopt fail:%d\n", WSAGetLastError());return -1;}printf("udp group start: %d, %d\n", IPPROTO_IP, IP_ADD_MEMBERSHIP);int len = sizeof(sockaddr);char strRecv[1024] = { 0 };while (true){memset(strRecv, 0, sizeof(strRecv));iRet = recvfrom(sock, strRecv, sizeof(strRecv) - 1, 0, (sockaddr*)&addr, &len);if (iRet <= 0) {printf("recvfrom fail:%d", WSAGetLastError());return -1;}printf("recv data:%s\n", strRecv);}closesocket(sock);WSACleanup();return 0;
}

经过对比发现Qt的源码中地址 mreq4.imr_interface.s_addr 赋值时候 QHostAddress firstIP = addressEntries.first().ip();可能为IPV6地址,导致IPV6地址赋值给IPV4地址,导致组播失败。

        if (iface.isValid()) {const QList<QNetworkAddressEntry> addressEntries = iface.addressEntries();if (!addressEntries.isEmpty()) {QHostAddress firstIP = addressEntries.first().ip();mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address());} else {d->setError(QAbstractSocket::NetworkError,QNativeSocketEnginePrivate::NetworkUnreachableErrorString);return false;}} else {mreq4.imr_interface.s_addr = INADDR_ANY;}

解决方案

  1. 更新Qt版本,最新版的Qt已经修复了这个问题
    if (iface.isValid()) {const QList<QNetworkAddressEntry> addressEntries = iface.addressEntries();bool found = false;for (const QNetworkAddressEntry &entry : addressEntries) {const QHostAddress ip = entry.ip();if (ip.protocol() == QAbstractSocket::IPv4Protocol) {mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());found = true;break;}}if (!found) {d->setError(QAbstractSocket::NetworkError,QNativeSocketEnginePrivate::NetworkUnreachableErrorString);return false;}} else {mreq4.imr_interface.s_addr = INADDR_ANY;}
  1. 修改代码如下
    在工程文件中添加
win32 {LIBS += -lWs2_32
}

修改关键代码

//添加头文件
#ifdef Q_OS_WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
//...........................//Qt 5.7 bug fix, 第一个IP可能为ip v6if (firstIP.protocol() == groupAddress.protocol()) {ok = udpsock->joinMulticastGroup(groupAddress, iface);} else {
#ifdef Q_OS_WIN32for (int i = 0; i < addressEntries.size(); i++) {QHostAddress addrTemp = addressEntries.at(i).ip();if (addrTemp.protocol() == groupAddress.protocol()) {ip_mreq multiCast;multiCast.imr_interface.S_un.S_addr = inet_addr(addrTemp.toString().toUtf8().constData());multiCast.imr_multiaddr.S_un.S_addr = inet_addr(groupAddress.toString().toUtf8().constData());int res = setsockopt(udpsock->socketDescriptor(),0,12,(char *) &multiCast,sizeof(multiCast));ok = (res == 0);break;}}
#elseok = udpsock->joinMulticastGroup(groupAddress, iface);
#endif

血的经验

  1. 使用三方标准工具测试
  2. 使用原始sdk测试
  3. Qt也可能存在bug
  4. 搜索引擎可能存在误导
  5. csdn === 田文镜

相关文章:

Qt低版本多网卡组播bug

原文地址 最近在某个项目中&#xff0c;发现了一个低版本Qt的bug&#xff0c;导致组播无法正常使用&#xff0c;经过一番排查&#xff0c;终于找到了原因&#xff0c;特此记录。 环境 Qt&#xff1a;5.7.0 mingw32操作系统&#xff1a;windows 11 现象 在Qt5.7.0版本中&…...

Leetcode:540. 有序数组中的单一元素

题目 给你一个仅由整数组成的有序数组&#xff0c;其中每个元素都会出现两次&#xff0c;唯有一个数只会出现一次。 请你找出并返回只出现一次的那个数。 你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。 输入: nums [1,1,2,3,3,4,4,8,8] 输出: 2 输入:…...

Python数据分析NumPy和pandas(二十七、数据可视化 matplotlib API 入门)

数据可视化或者数据绘图是数据分析中最重要的任务之一&#xff0c;是数据探索过程的一部分&#xff0c;数据可视化可以帮助我们识别异常值、识别出需要的数据转换以及为模型生成提供思考依据。对于Web开发人员&#xff0c;构建基于Web的数据可视化显示也是一种重要的方式。Pyth…...

数组指针和指针的区别

区分数组指针和指针数组 int *p[3]和 int (*p)[3] 根据运算符的优先级&#xff0c;"[]"的优先级是高于“*”的&#xff0c;p就会先与[]结合&#xff0c;那么它本质就是数组&#xff0c;数组内存放的是指针&#xff0c;它叫指针数组。&#xff08;int*p[3]&#xff…...

Linux git-bash配置

参考资料 命令提示符Windows下的Git Bash配置&#xff0c;提升你的终端操作体验WindowsTerminal添加git-bash 目录 一. git-bash配置1.1 解决中文乱码1.2 修改命令提示符 二. WindowsTerminal配置git-bash2.1 添加git-bash到WindowsTerminal2.2 解决删除时窗口闪烁问题 三. VS…...

【后端速成Vue】computed计算属性

前言&#xff1a; 本期将会介绍 Vue 中的计算属性&#xff0c;他和 methods 方法又会有什么区别呢&#xff1f;在这里都会给你一一讲解。 篮球哥找工作专属IT岗位内部推荐&#xff1a; 专属内推链接&#xff1a;内推通道 1、computed计算属性 概念&#xff1a; 基于现有的数据…...

力扣-每日温度

. - 力扣&#xff08;LeetCode&#xff09; 这是我的第一个思路 虽然可以得到正确答案 但是过于暴力 已经超出了时间限制 class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {vector<int>ans;for (int i 0; i <…...

(Go语言)初上手Go?本篇文章帮拿捏Go的数据类型!

1. bool 类型 布尔类型&#xff1a;只有 true 和 false 两种值 在Go中&#xff0c;整数 0 不代表 false 值&#xff0c;1也不代表 true 值 即数字无法代替布尔值进行逻辑判断&#xff0c;两者是完全不同的类型 布尔类型占用 1 字节 2. int 整型 Go中为不同位数的整数分配…...

支付宝域名如何加入白名单(扫码老是弹窗)

支付宝扫码之后,遇到非支付宝官方网页,请确认是否继续访问弹窗,问题解决办法。 本章教程提供解决办法,亲测有效。 一、打开支付宝开放平台 登录地址:https://open.alipay.com/ 然后进行扫码登录。 1、打开网页/移动应用开发 2、前往创建 3、创建应用...

嵌入式学习第21天Linux基础

目录 第1章 Linux 系统介绍 1.1 Unix 操作系统&#xff08;了解&#xff09; 1.2 Linux 操作系统&#xff08;了解&#xff09; 1.3 Linux 操作系统的主要特性&#xff08;重点&#xff09; 1.4 Linux 与 Unix 的区别与联系 1.5 GUN 与 GPL&#xff08;了解&#xff09; …...

【activiti工作流源码集成】springboot+activiti+mysql+vue+redis工作流审批流集成整合业务绑定表单流程图会签驳回

工作流集成实际项目案例&#xff0c;demo提供 源码获取方式&#xff1a;本文末个人名片直接获取。 前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;请假审批demo从流程绘制到审批结束实例。 一、项目形式 springbootvue…...

华为私有接口类型hybrid

华为私有接口类型hybrid Tip&#xff1a;hybrid类型&#xff0c;简称混合型接口。 本次实验模拟2层网络下 vlan10 vlan20 不能互访&#xff0c;vlan10 vlan20 同时可以访问vlan100 sw1配置如下&#xff1a; <Huawei>sy [Huawei]sys sw1 [sw1]vl ba 10 20 100 [sw1]int…...

计算机的错误计算(一百五十)

摘要 探讨 MATLAB 中 的计算精度问题。当 为含有小数的大数或 &#xff08;&#xff09;附近数时&#xff0c;输出会有错误数字。 例1. 已知 计算 直接贴图吧&#xff1a; 另外&#xff0c;16位的正确值分别为 -0.7882256119904400e0、0.1702266977524110e0、-0.…...

【模块化大作战】Webpack如何搞定CommonJS与ES6混战(3)

在前端开发中&#xff0c;模块化是一个重要的概念&#xff0c;不同的模块化标准有不同的特点和适用场景。webpack 同时支持 CommonJS 和 ES6 Module&#xff0c;因此需要理解它们在互操作时 webpack 是如何处理的。 同模块化标准 如果导出和导入使用的是同一种模块化标准&…...

工程认证与Spring Boot:计算机课程管理的新探索

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于工程教育认证的计算机课程管理平台的开发全过程。通过分析基于工程教育认证的计算机课程管理平台管理的不足&#xff0c;创建了一个计算机管理基于工程教育认…...

vue3的自定义hooks怎么写?

写个hook函数去追踪鼠标位置&#xff1a; 没用hook前&#xff1a; <script setup> import { ref, onMounted, onUnmounted } from vueconst x ref(0) const y ref(0)function update(event) {x.value event.pageXy.value event.pageY }onMounted(() > window.ad…...

SpringBoot项目编译报错 类文件具有错误的版本 61.0, 应为 52.0

springboot项目在编译时报错&#xff1a; /Users/Apple/Developer/art/caicai/cai-api/dubbo-samples/1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-provider/src/main/java/org/apache/dubbo/springboot/demo/provider/ProviderApplication.java:22:32 java…...

【网络】应用层——HTTP协议

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是HTTP协议。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;网络 &g…...

ServletContext介绍

文章目录 1、ServletContext对象介绍1_方法介绍2_用例分析 2、ServletContainerInitializer1_整体结构2_工作原理3_使用案例 3、Spring案例源码分析1_注册DispatcherServlet2_注册配置类3_SpringServletContainerInitializer 4_总结 ServletContext 表示上下文对象&#xff0c;…...

让AI帮我用java实现EasyExel读取图片—支持WPS嵌入图片

&#x1f308; 场景概述 java 小伙伴相信都使用 EasyExcel 以及 POI 库实现过 Excel 批量导入、导出功能&#xff0c;但只有部分人实现过 excel 导入带图片数据的场景。这个技术实现手段网上也有很多案例和demo&#xff0c;最常见的就是通过 XSSFPictureData 来实现。但是在 W…...

C# 实现对指定句柄的窗口进行键盘输入的实现

在C#中实现对指定句柄的窗口进行键盘操作&#xff0c;可以通过多种方式来实现。以下是一篇详细的指南&#xff0c;介绍如何在C#中实现这一功能。 1. 使用Windows API函数 在C#中&#xff0c;我们可以通过P/Invoke调用Windows API来实现对指定窗口的键盘操作。以下是一些关键的…...

深度学习之卷积问题

1 卷积在图像中有什么直观作用 ​ 在卷积神经网络中&#xff0c;卷积常用来提取图像的特征&#xff0c;但不同层次的卷积操作提取到的特征类型是不相同的&#xff0c;特征类型粗分如表1所示。 ​ 表1 卷积提取的特征类型 卷积层次特征类型浅层卷积边缘特征中层卷积局部特征深…...

yum安装zabbix5.0升级php到74的办法

【背景】 公司时不时有扫描漏洞,之前发现了php漏洞,因开启防火墙,限定IP+端口,暂时躲过升级;现在,老话重提,开启了KPI考核,躲是躲不过去的了,升级吧 【难题】 服务器为centos7,因操作系统问题,只能安装zabbix5.0。当时图省力,官网的办法,都是yum安装,很是简便。…...

JavaWeb合集23-文件上传

二十三 、 文件上传 实现效果&#xff1a;用户点击上传按钮、选择上传的头像&#xff0c;确定自动上传&#xff0c;将上传的文件保存到指定的目录中&#xff0c;并重新命名&#xff0c;生成访问链接&#xff0c;返回给前端进行回显。 1、前端实现 vue3AntDesignVue实现 <tem…...

当AI遇上时尚:未来的衣橱会由机器人来打理吗?

内容概要 在当今这个快速发展的时代&#xff0c;人工智能与时尚的结合正在逐渐改写我们对衣橱管理的认知。传统的衣橱管理常常面临着空间不足、穿搭单调及库存过多等挑战&#xff0c;许多人在挑选服饰时难以做出决策。然而&#xff0c;随着技术的进步&#xff0c;智能推荐和自…...

【初阶数据结构篇】二叉树OJ题

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…...

Windows系统中Oracle VM VirtualBox的安装

一.背景 公司安排了师带徒&#xff0c;环境搭建问题一直是初级程序员头疼的事情&#xff0c;我记录一下这些基础的内容&#xff0c;方便初学者。大部分开发者的机器还是windows系统&#xff0c;所以写了怎么安装。 二.版本信息及 操作系统&#xff1a;windows11 家庭版…...

go语言使用总结(持续更新)

整理后的内容如下&#xff1a; 1. 先了解函数签名&#xff0c;再了解传入参数以及调用 函数签名是函数的声明部分&#xff0c;包括函数名、参数列表和返回值列表。理解函数签名是理解函数行为的第一步&#xff0c;尤其是在了解参数类型、参数数量和返回值类型等方面。通过了解…...

如何在Android中自定义property

在Android中创建自定义的属性&#xff08;Android property&#xff09;通常用于调试、性能调优或传递应用和系统之间的信息。 以下是如何在Android中创建和使用自定义属性的步骤&#xff1a; 1. 定义属性 在Android中&#xff0c;属性是以“属性名称属性值”形式定义的键值对…...

机器学习5_支持向量机_原问题和对偶问题——MOOC

目录 原问题与对偶问题的定义 定义该原问题的对偶问题如下 在定义了函数 的基础上&#xff0c;对偶问题如下&#xff1a; 综合原问题和对偶问题的定义得到&#xff1a; 定理一 对偶差距&#xff08;Duality Gap&#xff09; 强对偶定理&#xff08;Strong Duality Theo…...

网站建设与优化/西安seo关键字优化

javaSE学习第十三天java知识 StringBuffer类的概述 A:StringBuffer类概述 通过JDK提供的API&#xff0c;查看StringBuffer类的说明 线程安全的可变字符序列 B:StringBuffer和String的区别 String是一个不可变的字符序列 StringBuffer是一个可变的字符序列 StringBuffer…...

网站打开慢如何优化/广州网站优化步骤

public static void main(String[] args) {Scanner scanner new Scanner(System.in);while (scanner.hasNext()) {String a scanner.nextLine();char[] b a.toCharArray();} 通过 next.line() 可以直接读取一串字符串但是不能像数组那样array[i]&#xff0c;对单个字符操作…...

微信怎么做网站推广/腾讯控股第三季度营收1401亿

题目&#xff1a;设m(x)是一个一致的3/4正确的蒙特卡罗算法&#xff0c;考虑下面的算法&#xff1a; public static int m3(int x) {int a,b,c;am(x);bm(x);cm(x);if((ab)||(ac))return a;return c;} &#xff08;1&#xff09;试证明算法m3(x)是一致的27/32正确的算法。&#…...

网站开发需要的人员/手机优化什么意思

计算机应用基础与操作(中国铁道出版社2014年出版图书)语音编辑锁定讨论上传视频本词条缺少概述图&#xff0c;补充相关内容使词条更完整&#xff0c;还能快速升级&#xff0c;赶紧来编辑吧&#xff01;《计算机应用基础与操作》由宋岐主编。本书主要介绍了计算机基础知识和操作…...

兼职做放单主持那个网站好/小红书搜索指数

在这之前&#xff0c;UWA在逻辑代码方面&#xff0c;可以反馈性能占用最为耗时的Top10函数运行效率&#xff0c;并配合运行截图快速了解它们的性能瓶颈&#xff0c;如下图所示。 我们都知道&#xff0c;这些函数中很可能包含了成百甚至上千行逻辑代码。比如&#xff0c;我们发现…...

对网站建设功能的情况说明/什么是seo

#-*- coding:utf-8 -*-#特征筛选的目标&#xff1a;一句话来说就是去冗余特征&#xff1b;与PCA不同&#xff0c;不会修改特征值&#xff0c;而是寻找那些对模型性能提升较大的少量特征#使用Titanic数据集&#xff0c;通过特征筛选的方法一步步提升决策树的预测性能import pand…...