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

SocketError TemporaryError (22) during UDP discovery



  • Hello to everybody,
    I have developed a routine to discover UDP servers in the local network. The server is a program who answer "OK" when receiving the datagram "discovery".

    QStringList getDiscoveredIPAddressList(quint16 numPort)
    {
        QStringList iplist;
        QUdpSocket Client;
        const char* szDiscovery = "discovery";
        Client.writeDatagram(szDiscovery, QHostAddress::Broadcast, numPort);
        // Give time to all UDP servers to read request and answer
        QThread::msleep(50);
        while (true)
        {
            char recbuffer[32] = { 0, };
            quint16 numPortTemp;
            QHostAddress qHostTemp;
            int nReceived = Client.readDatagram(recbuffer, sizeof(recbuffer) - 1, &qHostTemp, &numPortTemp);
            QString strErr;
            if (nReceived <= 0)
            {
                // No more IP addresses to discover
                strErr.sprintf("Socket error: %d", Client.error());
                qDebug() << strErr;
                break;
            }
            QString thisIp = qHostTemp.toString();
            thisIp.replace("::ffff:", "");
            iplist << thisIp;
        }
    
        return iplist;
    }
    

    This function works perfectly when compiled in Windows.
    However, when compiled with g++ in a VMware Ubuntu linux guest machine, it doesn't discover any server. After calling the readDatagram() method, the program outputs the following error:

    "Socket error: 22"
    

    The error 22 is described as follow:
    A temporary error occurred (e.g., operation would block and socket is non-blocking).

    Additional information:

    1. It doesn't help to repeat many times the call to readDatagram(), or to increase the sleep time after the call of writeDatagram. The error 22 is repeatedly emitted after every call of readDatagram, and the readDatagram does never return any datagram.

    2. With Wireshark I have seen that the datagram is sent to the broadcast address and that all the available UDP servers send the answer to the IP address of the UDP client, exactly as they do when the UDP client is compiled in windows (and in this case, as said, the client receives these answers). So the problem is not in sending the discovery message, but in receiving the answer.

    3. I have written another program in which the UDP client sends / receives messages to / from a specific UDP server address, instead of broadcast, and in this case the communication works perfectly both in Ubuntu and in WIndows. The only difference between the broadcast case is that I use the connectToHost() before sending the request to the UDP server (but of course this cannot be the solution because I cannot use the connectToHost() to connect to the broadcast IP address)

    4. I developed a simple UDP discovery program in Ubuntu using the native linux socket functions (sendto, recvfrom etc.) and it works perfectly. This remark is just to say that it is not a network problem of the Ubuntu machine.

    After much googleing I could not find anyone who faced the same issue. I spent many hours to make several variant and try possible solutions and I honestly came to a dead end.

    What is wrong in my code? Is it possible to enable some tracing / diagnostic functionsality to understand where is the error?
    Any help would be greatly appreciated.

    Thank you in advance


  • Lifetime Qt Champion

    @riffraff Instead of using a while loop you should use the assynchronous nature of Qt and connect a slot to QUdpSocket::readyRead signal where you can read.



  • @jsulm
    this is one of the other attempts that I did, without success. The hook (slot) function was never called.
    Anyway, the point of my post is not to find an alternative implementation of this snippet, but to understand why it doesn't work on linux, while in windows it works. Any idea? Can you explain why I get error 22?


  • Qt Champions 2020

    Use Client.waitFor{ReadyRead|BytesWritten} after {read|write}Datagram(). But it is wrong way, anyway.



  • @kuzulis
    Thank you for the suggestion, but unfortunately did not help.
    Update: I have opened the syslog viewer of Ubuntu and I have found this:

    Sep 25 20:28:01 ubuntu kernel: [18037.619107] [UFW BLOCK] IN=ens33 OUT= MAC=00:0c:29:a3:01:66:84:a9:3e:87:20:e1:08:00 SRC=10.10.20.12 DST=10.10.20.15 LEN=31 TOS=0x00 PREC=0x00 TTL=128 ID=9523 PROTO=UDP SPT=11000 DPT=41558 LEN=11
    

    The incoming connection was blocked by the UFW (uncomplicated firewall). So I have disabled it:

    sudo ufw disable
    

    Afterwards, this simple and uncomplicated function, even though wrong, works like a charm



  • @riffraff said in SocketError TemporaryError (22) during UDP discovery:

    works like a charm

    so please don't forget to mark your post as solved then!


Log in to reply