Qt程序只接收特定IP地址的UDP数据包

3
我有一个问题,关于Qt程序只能在STM32模块设置为某些看似随机但特定的IP地址时接收UDP [Artnet]数据包。所以,我有以下内容:
1. 运行动态IP地址的Linux机器上运行Qt程序 2. 运行手动设置为地址A的FreeRTOS模块的STM32 3. 运行手动设置为地址B的FreeRTOS模块的STM32
我编写了Qt软件,并在STM32板上使用了带有FreeRTOS的uIP - 修改uIP以正确使用UDP并添加简单的Artnet代码。所有设备都在192.168.0.x子网上。
我编写了Qt程序以向子网广播地址发送Artnet轮询。因此,它将标准的Artnet轮询发送到UDP端口6454的地址192.168.0.255。 Wireshark显示我的两个STM32模块返回Artnet Poll Replies非常好。到目前为止,一切正常。
然而,当我将其中一个STM32的IP地址设置为192.168.0.177,另一个设置为192.168.0.176时,177节点被Qt程序看到和处理,但是尽管176节点发送回正确的Artnet poll reply,Qt程序却断然拒绝读取回复数据包。如果我将176节点的IP地址更改为.44,则Qt程序会处理回复。如果我将[工作的].177节点更改为,例如.43,则不起作用。
我应该强调,无论我将STM32设置为什么IP地址,Wireshark都表明回复正常。
请问有人能提供任何可能阐明这一点的建议吗?我已经尝试了netcat,但似乎无论来自哪个地址,它都不能读取这些Artnet回复,因此我可能误解了netcat的功能。我已经尝试了Qt程序只打开出站端口而不是入站端口的netcat,但没有任何区别,但再次,我可能完全误解了netcat或UDP的某些内容。也许如果您打开出站UDP端口,则同样的入站将自动打开?
在我的Linux机器上没有IP地址冲突,也没有打开防火墙。
非常感谢。
编辑:根据要求添加了代码。
void MainWindow::processPendingDatagrams(void)
{
    struct ArtNetPollReplyStruct *newReply;
    QHostAddress sendingAddress;
    quint16 sendingUdpPort;
    QString versionString;
    QByteArray datagram;

    while (udpReceiveSocket->hasPendingDatagrams())
    {       
        datagram.resize(udpReceiveSocket->pendingDatagramSize());
        udpReceiveSocket->readDatagram(datagram.data(), datagram.size(), &sendingAddress,&sendingUdpPort);
        newReply = (struct ArtNetPollReplyStruct*)(datagram.data());
        if (newReply->OpCode == OP_POLL_REPLY)
            {
            if (sendingAddress != QHostAddress("192.168.0.18"))
                {
                if (checkAndAddAddress(sendingAddress))
                    {
                    versionString = QString::number(newReply->VersionInfoH,10) + "." + QString::number(newReply->VersionInfo,10);
                    addNodeToList(sendingAddress.toString(), versionString);
                    ui->textEdit->append( QString::fromUtf8(newReply->LongName));
                    }
                }
            }
        }
}

初始化UDP端口的代码如下:

udpSendSocket = new QUdpSocket(this); udpReceiveSocket = new QUdpSocket(this);    
udpSendSocket->bind(6454, QUdpSocket::ShareAddress); 
udpReceiveSocket->bind(QHostAddress::Any,6454);
connect(udpReceiveSocket, SIGNAL(readyRead()),this, SLOT(processPendingDatagrams()));
connect(ui->innoLEDListTable,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(tableItemClicked(QTableWidgetItem*)));

$ ifconfig
enp5s0    Link encap:Ethernet  HWaddr 14:DA:E9:30:36:22  
          inet addr:192.168.0.18  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:265615 errors:0 dropped:0 overruns:0 frame:0
          TX packets:190104 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:306893983 (292.6 MiB)  TX bytes:20997451 (20.0 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:25205 errors:0 dropped:0 overruns:0 frame:0
          TX packets:25205 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6063842 (5.7 MiB)  TX bytes:6063842 (5.7 MiB)

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.2     0.0.0.0         UG    10     0        0 enp5s0
169.254.0.0     0.0.0.0         255.255.0.0     U     10     0        0 enp5s0
192.168.0.0     0.0.0.0         255.255.255.0   U     10     0        0 enp5s0

如果没有您展示读取数据包的源代码,这个问题是无法回答的。请提供一个最小的示例:从一个空的 main.cpp 文件开始,只添加设置套接字并将数据包放入 QByteArray 所需的最少量的代码。到那时,问题应该会自行展示,我希望如此。 - Kuba hasn't forgotten Monica
请在Linux机器上显示“ifconfig”和“route -n”输出。 - Kuba hasn't forgotten Monica
我已按要求添加了信息。当IP地址更改为,比如说,.176时,processPendingDatagrams()函数根本不会被调用,因此我认为这不是Qt代码的问题。不过,如果有证据证明我错了,我也很乐意接受!非常感谢 :) - DiBosco
1个回答

2

您只需要一个套接字。您的问题是数据报到达另一个套接字,而您从未从中读取。套接字是双向的。


哇,你说得对。Qt邮件列表上没有人注意到这一点,很棒的发现。这是我第一次在任何东西上使用UDP/IP,更不用说Qt了。非常感谢。 - DiBosco
@DiBosco 这与Qt无关。如果您直接使用POSIX / Unix API,情况将是相同的。不幸的是,我之所以注意到它,是因为我让您发布了相关代码。我不知道邮件列表上是否有人看到了那段代码。所以,几乎总是这样,问题提问者没有发布完整、可编译、最小化的示例来展示他们的困境,反而自己给自己惹麻烦。看看我的答案。我发布了100多个Qt答案,其中包括自包含的单文件示例。有些相当复杂 :) - Kuba hasn't forgotten Monica
@DiBosco,问题的一部分是变量命名具有误导性:udpSendSocket并不仅仅是一个发送套接字。一种有用的调试技巧是想象所有变量都有没有意义的名称 :) - Kuba hasn't forgotten Monica
问题是,我以为它是一个有意义的名称。这是无知的表现,不知道一旦打开UDP套接字,它就是双向的!:~) - DiBosco
我在Qt邮件列表上发布了代码,顺便说一下。我收到了很多回复,有几个人提出了建议,其中大部分都提到了发送和接收套接字!我想知道是否有很多人在不同的端口上发送和接收,因此需要两个套接字?(纯属猜测。) - DiBosco
@DiBosco我认为他们也被变量名愚弄了 :) 我真的很想知道那些回复的人中有多少人在生产环境中使用过UDP套接字,以及他们的数据包丢失率是多少。也许每个人和他们的狗都会丢失一半的数据包,但是他们在UDP之上使用的协议可以处理它? :) - Kuba hasn't forgotten Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接