局域网中提供一个服务,比如提供Qt RO网络中的注册中心的url, 可以考虑使用组播技术.
对于多网卡来说, udp加入组播地址,并绑定端口后,不一定能够收到客户端发送的查询消息,估计是因为消息所在的网络不一定就是绑定的网卡所在的网络,在虚拟机上测试时,会出现这种情况.
现象重现: 服务端在本机上执行, 客户端在虚拟机上执行,客户端向组播地址发送的消息,在NAT模式下,因为ip地址不在同一个网段,数据包不会继续传递,就会造成这种现象
解决的思路就是用每一个网口绑定一个udp就行.
迭代网口,如果网卡激活:IsUp,并且能够组播 CanMulticast,而且不是回环 interface.name().contains(“loopback”),那就构造一个udp,并使用该网卡进行绑定,加入组播
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QNetworkDatagram>
#include <QNetworkInterface>
#include <QTimer>
#define qout qDebug() << __FILE__ << __LINE__
Widget::Widget(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
auto allInterface = QNetworkInterface::allInterfaces();
for (int i = 0; i < allInterface.size(); ++i) {
auto interface = allInterface.at(i);
if (interface.flags() & QNetworkInterface::IsUp) {
if (interface.flags() & QNetworkInterface::CanMulticast) {
if (!interface.name().contains("loopback")) {
auto udp = new QUdpSocket(this);
udp->bind(QHostAddress::AnyIPv4, 62224,
QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint);
udp->joinMulticastGroup(QHostAddress("224.2.2.2"), interface);
connect(udp, &QUdpSocket::readyRead,
this, &Widget::readPendingDatagrams);
qout << interface;
}
}
}
}
// auto* timer = new QTimer(this);
// connect(timer, &QTimer::timeout, [this] {
// this->multiSendMsg();
// });
// timer->start(5000);
}
Widget::~Widget() { delete ui; }
// 1. 多播接收,对点发送
void Widget::readPendingDatagrams()
{
auto udp = (QUdpSocket*)sender();
while (udp->hasPendingDatagrams()) {
QNetworkDatagram datagram = udp->receiveDatagram();
qout << "receive msg" << datagram.data();
qout << datagram.senderAddress() << datagram.senderPort();
QString msg = "tcp://192.168.101.121:9999";
udp->writeDatagram(
msg.toUtf8(),
datagram.senderAddress(),
datagram.senderPort());
}
}