Qt multicast works from Windows to Mac but not another around



  • 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
    

    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
    

    Here is the source code

    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
    

    Multicast.cpp

    #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);
    	}
    }
    

    main.cpp

    #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();
    }
    

    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)
    			}
    		}
    	}
    }


  • Using wireshark to monitor the traffic, the message from Mac dose arrive on Windows.



  • Just found on Windows the multicast group in bound to interface 4 Ethernet. But my program multicastInterface output 8 Local Area Connection.

    Do I need 2 separate sockets for receiving and sendin individually?



  • The cause is the VirtualBox network card steals multicasting.This is a known issue in VirtualBox.

    Disable the network interface or set a high Metic in settings solves the problem.

    Now I need to find out if it's feasible to bind a socket on a specific interface.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.