I use an experimental project to test Qt multicast. It's acting like a simple chat program within a local network. I'm able to send messages from Windows to Mac, but not from Mac to Windows. Please see the comment in Multicast.cpp.
Both of them join a predefined group. I used some hard coded IP to find the corresponding interface to bind to. I have also checked the multicast groups on both platforms using netstat and netsh and it show the predefined group on both sides.
It's not a firewall issue, since I turned it off and the issue persisted.
Qt version:5.5
Any suggestion what I should do next to diagnose this issue?
netsh output:
C:\Users\Jerry>netsh interface ip show joins
Interface 1: Loopback Pseudo-Interface 1
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 1 Yes 224.0.0.251
0 4 Yes 239.255.255.250
Interface 4: Ethernet
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 0 Yes 224.0.0.1
0 2 Yes 224.0.0.251
0 1 Yes 224.0.0.252
0 0 Yes 239.255.43.21
0 4 Yes 239.255.255.250
Interface 8: Local Area Connection
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 0 Yes 224.0.0.1
0 2 Yes 224.0.0.251
0 1 Yes 224.0.0.252
0 4 Yes 239.255.255.250
C:\Users\Jerry>netsh interface ip show joins
Interface 1: Loopback Pseudo-Interface 1
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 1 Yes 224.0.0.251
0 4 Yes 239.255.255.250
Interface 4: Ethernet
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 0 Yes 224.0.0.1
0 2 Yes 224.0.0.251
0 1 Yes 224.0.0.252
0 0 Yes 239.255.43.21
0 4 Yes 239.255.255.250
Interface 8: Local Area Connection
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 0 Yes 224.0.0.1
0 2 Yes 224.0.0.251
0 1 Yes 224.0.0.252
0 4 Yes 239.255.255.250
To copy to clipboard, switch view to plain text mode
netstat output
eve:~ Jerry$ netstat -g
Link-layer Multicast Group Memberships
Group Link-layer Address Netif
1:0:5e:7f:2b:15 <none> en0
1:0:5e:0:0:fb <none> en0
1:0:5e:0:0:1 <none> en0
33:33:ff:c9:32:14 <none> en0
33:33:0:0:0:fb <none> en0
33:33:ff:41:27:e <none> en0
33:33:0:0:0:1 <none> en0
33:33:ff:33:5b:7a <none> en0
1:80:c2:0:0:3 <none> en0
33:33:0:0:0:fb <none> en1
1:3:93:df:b:92 <none> en1
33:33:0:0:0:fb <none> awdl0
33:33:80:0:0:fb <none> awdl0
IPv4 Multicast Group Memberships
Group Link-layer Address Netif
224.0.0.251 <none> lo0
224.0.0.1 <none> lo0
239.255.43.21 1:0:5e:7f:2b:15 en0
224.0.0.251 1:0:5e:0:0:fb en0
224.0.0.1 1:0:5e:0:0:1 en0
IPv6 Multicast Group Memberships
Group Link-layer Address Netif
ff02::fb%lo0 <none> lo0
ff02::2:ff33:9cc0%lo0 <none> lo0
ff01::1%lo0 <none> lo0
ff02::1%lo0 <none> lo0
ff02::1:ff00:1%lo0 <none> lo0
ff02::1:ffc9:3214%en0 33:33:ff:c9:32:14 en0
ff02::fb%en0 33:33:0:0:0:fb en0
ff01::1%en0 33:33:0:0:0:1 en0
ff02::2:ff41:270e%en0 33:33:ff:41:27:e en0
ff02::1%en0 33:33:0:0:0:1 en0
ff02::1:ff33:5b7a%en0 33:33:ff:33:5b:7a en0
ff02::fb%en1 33:33:0:0:0:fb en1
ff02::fb%awdl0 33:33:0:0:0:fb awdl0
eve:~ Jerry$ netstat -g
Link-layer Multicast Group Memberships
Group Link-layer Address Netif
1:0:5e:7f:2b:15 <none> en0
1:0:5e:0:0:fb <none> en0
1:0:5e:0:0:1 <none> en0
33:33:ff:c9:32:14 <none> en0
33:33:0:0:0:fb <none> en0
33:33:ff:41:27:e <none> en0
33:33:0:0:0:1 <none> en0
33:33:ff:33:5b:7a <none> en0
1:80:c2:0:0:3 <none> en0
33:33:0:0:0:fb <none> en1
1:3:93:df:b:92 <none> en1
33:33:0:0:0:fb <none> awdl0
33:33:80:0:0:fb <none> awdl0
IPv4 Multicast Group Memberships
Group Link-layer Address Netif
224.0.0.251 <none> lo0
224.0.0.1 <none> lo0
239.255.43.21 1:0:5e:7f:2b:15 en0
224.0.0.251 1:0:5e:0:0:fb en0
224.0.0.1 1:0:5e:0:0:1 en0
IPv6 Multicast Group Memberships
Group Link-layer Address Netif
ff02::fb%lo0 <none> lo0
ff02::2:ff33:9cc0%lo0 <none> lo0
ff01::1%lo0 <none> lo0
ff02::1%lo0 <none> lo0
ff02::1:ff00:1%lo0 <none> lo0
ff02::1:ffc9:3214%en0 33:33:ff:c9:32:14 en0
ff02::fb%en0 33:33:0:0:0:fb en0
ff01::1%en0 33:33:0:0:0:1 en0
ff02::2:ff41:270e%en0 33:33:ff:41:27:e en0
ff02::1%en0 33:33:0:0:0:1 en0
ff02::1:ff33:5b7a%en0 33:33:ff:33:5b:7a en0
ff02::fb%en1 33:33:0:0:0:fb en1
ff02::fb%awdl0 33:33:0:0:0:fb awdl0
To copy to clipboard, switch view to plain text mode
Here is the source code
Multicast.h
#ifndef MULTICAST_H
#define MULTICAST_H
#include <QQuickItem>
#include <QHostAddress>
#include <QNetworkInterface>
class Multicast : public QQuickItem
{
Q_OBJECT
public:
Multicast();
Q_INVOKABLE
void multicast
(QString s
);
signals:
void messageAdded
(const QString msg
);
private slots:
void processPendingDatagrams();
private:
private:
};
#endif // MULTICAST_H
#ifndef MULTICAST_H
#define MULTICAST_H
#include <QQuickItem>
#include <QHostAddress>
#include <QNetworkInterface>
class QUdpSocket;
class Multicast : public QQuickItem
{
Q_OBJECT
public:
Multicast();
Q_INVOKABLE void multicast(QString s);
signals:
void messageAdded(const QString msg);
private slots:
void processPendingDatagrams();
private:
QNetworkInterface getNetworkInterfaceByAddress(QString adr);
void printNetworkInterfaceInfo(QNetworkInterface ni);
private:
QHostAddress groupAddress;
QUdpSocket *udpSocket;
};
#endif // MULTICAST_H
To copy to clipboard, switch view to plain text mode
Multicast.cpp
#include "multicast.h"
#include <QtNetwork>
Multicast::Multicast()
{
// hard coded group
// hard coded IP to find network interface. 10.0.1.40 for the other devices
// if I don't manually set this interface, and set loopback to 1,
// this can receive the message from itself. Otherwise, it receives
// nothing.
udpSocket->setMulticastInterface(getNetworkInterfaceByAddress("10.0.1.39"));
bool r = udpSocket->joinMulticastGroup(groupAddress);
printNetworkInterfaceInfo(intf);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(processPendingDatagrams()));
}
{
for (int i = 0; i < il.size(); i++)
{
QList<QNetworkAddressEntry> ade(il[i].addressEntries());
for (int j = 0; j < ade.size(); j++)
{
if (ade[j].ip().toString() == adr)
return il[i];
}
}
}
{
qDebug() << ni.index() << ni.humanReadableName();
QList<QNetworkAddressEntry> ade(ni.addressEntries());
for (int j = 0; j < ade.size(); j++)
qDebug() << ade[j].ip();
}
void Multicast
::multicast(QString msg
) {
udpSocket->writeDatagram(datagram.data(), datagram.size(),
groupAddress, 45454);
}
void Multicast::processPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
emit messageAdded(data);
}
}
#include "multicast.h"
#include <QtNetwork>
Multicast::Multicast()
{
// hard coded group
groupAddress = QHostAddress("239.255.43.21");
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::AnyIPv4, 45454, QUdpSocket::ShareAddress);
// hard coded IP to find network interface. 10.0.1.40 for the other devices
// if I don't manually set this interface, and set loopback to 1,
// this can receive the message from itself. Otherwise, it receives
// nothing.
udpSocket->setMulticastInterface(getNetworkInterfaceByAddress("10.0.1.39"));
bool r = udpSocket->joinMulticastGroup(groupAddress);
udpSocket->setSocketOption(QAbstractSocket::MulticastLoopbackOption, QVariant(1));
QNetworkInterface intf(udpSocket->multicastInterface());
printNetworkInterfaceInfo(intf);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(processPendingDatagrams()));
}
QNetworkInterface Multicast::getNetworkInterfaceByAddress(QString adr)
{
QList<QNetworkInterface> il(QNetworkInterface::allInterfaces());
for (int i = 0; i < il.size(); i++)
{
QList<QNetworkAddressEntry> ade(il[i].addressEntries());
for (int j = 0; j < ade.size(); j++)
{
if (ade[j].ip().toString() == adr)
return il[i];
}
}
return QNetworkInterface();
}
void Multicast::printNetworkInterfaceInfo(QNetworkInterface ni)
{
qDebug() << ni.index() << ni.humanReadableName();
QList<QNetworkAddressEntry> ade(ni.addressEntries());
for (int j = 0; j < ade.size(); j++)
qDebug() << ade[j].ip();
}
void Multicast::multicast(QString msg)
{
QByteArray datagram = msg.toUtf8();
udpSocket->writeDatagram(datagram.data(), datagram.size(),
groupAddress, 45454);
}
void Multicast::processPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
QString data(datagram);
emit messageAdded(data);
}
}
To copy to clipboard, switch view to plain text mode
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "multicast.h"
int main(int argc, char *argv[])
{
qmlRegisterType<Multicast>("com.multicast.test", 1, 0, "Multicast");
QQmlApplicationEngine engine;
engine.
load(QUrl(QStringLiteral
("qrc:/main.qml")));
return app.exec();
}
#include <QApplication>
#include <QQmlApplicationEngine>
#include "multicast.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
qmlRegisterType<Multicast>("com.multicast.test", 1, 0, "Multicast");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
To copy to clipboard, switch view to plain text mode
main.qml
import QtQuick 2.3
import QtQuick.Controls 1.2
import com.multicast.test 1.0
ApplicationWindow {
id: applicationWindow1
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Multicast {
id : multicast
}
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("&Open")
onTriggered: console.log("Open action triggered");
}
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
TextInput {
id: textInput1
y: 57
width: 450
height: 20
text: qsTr("Text Input")
anchors.left: parent.left
anchors.leftMargin: 50
font.pixelSize: 12
}
Button {
id: button1
y: 57
text: qsTr("Button")
anchors.left: textInput1.right
anchors.leftMargin: 20
onClicked: {
textEdit1.append(textInput1.text)
multicast.multicast(textInput1.text)
textInput1.text = ""
}
}
TextEdit {
id: textEdit1
y: 106
height: 327
readOnly: true
anchors.left: parent.left
anchors.leftMargin: 50
anchors.right: parent.right
anchors.rightMargin: 50
font.pixelSize: 12
Connections {
target: multicast
onMessageAdded: {
textEdit1.append(msg)
}
}
}
}
import QtQuick 2.3
import QtQuick.Controls 1.2
import com.multicast.test 1.0
ApplicationWindow {
id: applicationWindow1
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Multicast {
id : multicast
}
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("&Open")
onTriggered: console.log("Open action triggered");
}
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
TextInput {
id: textInput1
y: 57
width: 450
height: 20
text: qsTr("Text Input")
anchors.left: parent.left
anchors.leftMargin: 50
font.pixelSize: 12
}
Button {
id: button1
y: 57
text: qsTr("Button")
anchors.left: textInput1.right
anchors.leftMargin: 20
onClicked: {
textEdit1.append(textInput1.text)
multicast.multicast(textInput1.text)
textInput1.text = ""
}
}
TextEdit {
id: textEdit1
y: 106
height: 327
readOnly: true
anchors.left: parent.left
anchors.leftMargin: 50
anchors.right: parent.right
anchors.rightMargin: 50
font.pixelSize: 12
Connections {
target: multicast
onMessageAdded: {
textEdit1.append(msg)
}
}
}
}
To copy to clipboard, switch view to plain text mode
Added after 1 8 minutes:
Using wireshark to monitor the traffic, the message from Mac dose arrive on Windows.
Bookmarks