Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QUdpSocket receiveDatagram fails on Linux (ubuntu 18.04)



  • Hello!
    I'm trying to make a simple communication module for a software I'm working on, based on UDP Multicast, but I'm having problems to receive the datagrams on linux.

    I Have a QUdpSocket initialized as follows:

    socket = new QUdpSocket();
    QNetworkInterface iface = QNetworkInterface::interfaceFromName(interfaceName);
    QHostAddress interfaceAddr = iface.addressEntries().first().ip();		
    connect(socket, &QUdpSocket::readyRead, this, &MeshMessenger::bytesReceived);
    connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QUdpSocket::error), this, &MeshMessenger::socketErrors);
    
    if(!socket->bind(interfaceAddr, port))
    	qWarning() << "[MeshMessenger::init] Failed to bind, error:" << socket->error();
    
    else if(!socket->joinMulticastGroup(multicastGroup, iface))
    	qWarning() << "[MeshMessenger::init] Failed to join multicast group, error:" << socket->error();
    
    else
    {
    	state = ONLINE;
    	ret = true;
    }
    

    The bytesReceived slot is implemented as follows:

    void MeshMessenger::bytesReceived()
    {
    	while(socket->hasPendingDatagrams())
    	{
    		QNetworkDatagram data = socket->receiveDatagram();
    		if(data.isValid())
    		{
    			//Data processing goes here.
    		}
    	}
    }
    

    This code runs fine on Windows 10 x64 (Qt 5.12.8 MSVC 2017), but does not on Ubuntu 18.04 x64 (Qt 5.12.8 GCC).

    On Linux, the bytesReceived slot is called the first time a datagram arrives, and the socket->hasPendingDatagrams() call returns true, but the QNetworkDatagram object returned by the socket->receiveDatagram() call is not valid.

    I tried to use the old API (QUdpSocket::pendingDatagramSize and QUdpSocket::readDatagram), but the behavior was weird. As before, QUdpSocket::hasPendingDatagrams returns true, but QUdpSocket::pendingDatagramSize returns -1 (which, according to the documentation, means there is no datagram waiting to be read), while QUdpSocket::bytesAvailable returned the correct datagram size. Using this, I was able to read the datagrams using QUdpSocket::readDatagram, but this is not what the documentation (and the examples) instruct to do, so I don't know if its safe to assume that the size returned by QUdpSocket::bytesAvailable is the size of the first datagram in the buffer (as QUdpSocket::pendingDatagramSize is)

    Am I doing something wrong? Or is this a bug?

    EDIT:

    After further testing, I noticed that the behavior is a little different on "real" Linux.

    I was developing under the WSL (Windows Subsystem for Linux) for Ubuntu 18.04, and tests outside the debugger, being made on Ubuntu VMs through Virtualbox. Since the simptoms were the same, I thought that the same problem was happening in both environments. But, after i put a debug line as the first command of the MeshMessenger::bytesReceived slot, I noticed that the slot wasn't being called in the VM environment, only in WSL.

    So I built another ubuntu VM with the dev environment, and confirmed it: under Linux, the readyRead is not being emitted. The datagrams are written normally, but no datagrams are being received by the application.

    Wireshark on both ends (Windows and inside the Ubuntu VM) sees the udp Datagrams flowing, and on windows, my application can see the datagrams.

    So, I have three differente behaviours:

    1. On Windows, it works normally, as the documentation says so.
    2. On WSL Ubuntu, It's as I explained in the OP.
    3. On Native Ubuntu (VM), The readyRead signal isn't even emitted.

Log in to reply