网站专题页面制作,pycharm 做网站哪个好,wordpress 第一张图片不显示,2022网站快速收录技术原文地址 最近在某个项目中#xff0c;发现了一个低版本Qt的bug#xff0c;导致组播无法正常使用#xff0c;经过一番排查#xff0c;终于找到了原因#xff0c;特此记录。 环境
Qt#xff1a;5.7.0 mingw32操作系统#xff1a;windows 11
现象
在Qt5.7.0版本中…原文地址 最近在某个项目中发现了一个低版本Qt的bug导致组播无法正常使用经过一番排查终于找到了原因特此记录。 环境
Qt5.7.0 mingw32操作系统windows 11
现象
在Qt5.7.0版本中使用组播发送数据时发现数据无法接收经过长时间的排查发现是Qt的bug具体现象如下
在Qt5.7.0版本中使用组播发送数据时发现数据无法接收。使用串口调试工具发现发送的数据包没有问题无论何种情况都可以。使用wireshark抓包发现发送的数据包没有问题。使用Qt自带的组播收发例子本机测试发现可以正常接收数据但是当收发处于两台电脑时不能接收。
排查步骤 使用调试工具 使用地址 0.0.0.0: port 不能接收到数据使用地址 192.168.1.100: port 可以接收到数据使用地址 239.255.255.255: port 不能接收到数据 测试自带的组播收发例子 本机测试可以正常接收数据两台电脑测试不能接收数据
尝试解决
经过一顿搜索加上长时间的摸索本机的虚拟网卡太多长时间折腾后发现只有一个网卡的时候可以正常。必须祭出终极大杀器 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 QListQNetworkAddressEntry 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;}解决方案
更新Qt版本最新版的Qt已经修复了这个问题 if (iface.isValid()) {const QListQNetworkAddressEntry 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;}修改代码如下 在工程文件中添加
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血的经验
使用三方标准工具测试使用原始sdk测试Qt也可能存在bug搜索引擎可能存在误导csdn 田文镜