Qt5: connectToHost() 接收广播udp数据报

Qt5: connectToHost() to receive broadcast udp datagram

我可以使用 QAbstractSocket::connectToHost() 来接收广播 udp 数据报吗?

如果我尝试未修改的 broadcastsender/receiver 一切正常,netstat 是:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
udp6       0      0 :::52337                :::*                                12185/./broadcastse 
udp6       0      0 :::45454                :::*                                12172/broadcastrece

我修改了broadcastreceiver如下:

//! [0]
    udpSocket = new QUdpSocket(this);
    udpSocket->bind(45454, QUdpSocket::ShareAddress);
    udpSocket->connectToHost(QHostAddress(QHostAddress::Any),0); // <- added line
//! [0]

现在它不接收广播数据报,但它能正确接收单播数据报。

netstat 命令报告为:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
udp6       0      0 ::1:45454               ::1:*                   ESTABLISHED 11488/broadcastrece

我想知道为什么本地地址看起来不同,我哪里错了。

此致 最大值

如果您查看 official documentation of QUdpSocket,您将看到以下段落,它很好地解释了如何使用 QUdpSocket:

The most common way to use this class is to bind to an address and port using bind(), then call writeDatagram() and readDatagram() / receiveDatagram() to transfer data. If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to a peer by calling connectToHost().

所以你对 connectToHost() 的调用是 没有必要,你应该改为只绑定然后监听信号 readyRead() 并从插槽中使用readDatagram() 获取原始数据包数据或 receiveDatagram() 获取预解析数据。

这似乎违反直觉,但由于 UDP 协议的性质,没有连接,任何节点都可以向任何其他未发起的节点发送数据包,所以一旦你 bind() 你可以收到来自任何人的 UDP 数据包。

在这种情况下,源地址和端口将成为数据报本身的一部分。您可以在 receiveDatagram() 函数签名的参数中看到这一点:

qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)

请注意,您可能会遇到通过 UDP 进行通信的问题,因为任何转换网关(NAT 路由器)都会丢弃所有未启动的数据包。这是一个常见问题,除非您控制端点之间的路由器,否则需要一些 clever tricks 才能绕过。

希望这对您有所帮助。