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

UDP packets received only the first time.



  • Hi All, i'm having this weird problem, i only receive the udp packets the first time i send them, all after that aren't shown anymore.

    Here is what i have, can you please help me figure out what the problem is ?:

    receiver.h

    #ifndef RECEIVER_HPP
    #define RECEIVER_HPP
    
    #include <QtCore/QObject>
    
    class QUdpSocket;
    
    /**
         * The Receiver class handles the processing of the incoming UDP datagrams.
         * It uses a QUdpSocket to retrieve the datagrams and makes the content of
         * the datagram available to the UI via the 'status' property.
         */
    class Receiver : public QObject
    {
        Q_OBJECT
        
        // The property that makes the content of a received datagram available to the UI
        Q_PROPERTY(QString status READ status NOTIFY statusChanged)
        
    public:
        void initSocket();
        Receiver(QObject *parent = 0);
        
    Q_SIGNALS:
        // The change notification signal of the status property
        void statusChanged();
        
    private slots:
        void processPendingDatagrams();
        
    private Q_SLOTS:
        // This method is called whenever a new datagram arrived on the socket
        //    void processPendingDatagrams();
        
    private:
        // The accessor method of the status property
        QString status() const;
        
        // The UDP socket object
        QUdpSocket *m_udpSocket;
        
        // The content of the received datagram
        QString m_status;
    };
    
    #endif
    
    

    receiver.cpp

    #include "receiver.h"
    #include <QThread>
    #include <QtNetwork/QUdpSocket>
    
    Receiver::Receiver(QObject *parent)
        : QObject(parent)
    {
        /**
             * Initialize the 'status' property with no data, it won't
             * be shown in the UI until the first datagram arrives.
    
    
    */
        m_status = "--";
    
        m_udpSocket = new QUdpSocket(this);
            m_udpSocket->bind(QHostAddress::AnyIPv4, 4210);
    
            processPendingDatagrams();
            connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection);
    
        /*
        // Create a new UDP socket and bind it against port 45454
        m_udpSocket = new QUdpSocket(this);
        if(m_udpSocket->bind(QHostAddress::LocalHost, 4210))
            qDebug() << "Bind true on port" << 4210;
        else
            qDebug() << "Bind super failed";
    
    
    
             * Create signal/slot connection to invoke processPendingDatagrams() whenever
             * a new datagram is received by the socket.
    
      //  connect(m_udpSocket, SIGNAL(readyRead()), this,
       //         SLOT(processPendingDatagrams()));*/
    }
    
    void Receiver::initSocket(){
        QByteArray Data;
            Data.append("Hello from UDP");
    
            // Sends the datagram datagram
            // to the host address and at port.
            // qint64 QUdpSocket::writeDatagram(const QByteArray & datagram,
            //                      const QHostAddress & host, quint16 port)
    
    //             m_udpSocket->writeDatagram(Data, QHostAddress::LocalHost, 4210);
    
    }
    
    void Receiver::processPendingDatagrams()
    {
    
        // Now read all available datagrams from the socket
        while (m_udpSocket->hasPendingDatagrams()) {
    
    
            // Create a temporary buffer ...
            QByteArray datagram;
    
            QHostAddress sender;
            quint16 senderPort;
        qDebug() << "2 ";
            // ... with the size of the received datagram ...
            datagram.resize(m_udpSocket->pendingDatagramSize());
    
            // ... and copy over the received datagram into that buffer.
            m_udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
    
            // Update the 'status' property with the content of the received datagram
      //      m_status = tr("%1").arg(datagram.data());
    
    
    
             qDebug() << "Message from: " << sender.toString();
             qDebug() << "Message port: " << senderPort;
             qDebug() << "Message: " << datagram;
    
    
    
        //    emit statusChanged();
        }
    }
    
    QString Receiver::status() const
    {
        return m_status;
    }
    
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include<QDebug>
    #include <QQmlEngine>
    #include <QQmlComponent>
    #include <QQmlProperty>
    #include "receiver.h"
    #include <QQmlContext>
    #include "touchitem.h"
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    int main(int argc, char *argv[])
    {
    
    
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
     //   QCoreApplication::setAttribute(Qt:QT_QPA_EGLFS_HIDECURSOR, true);
        QCoreApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
    
    
    
        QGuiApplication app(argc, argv);
        app.setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
        QQmlApplicationEngine engine;
            QObject::connect(&app, &QGuiApplication::aboutToQuit, &thread, &Thread::stop);
    
        engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
        const QUrl url(QStringLiteral("qrc:/main.qml"));
    
    
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
    
        }, Qt::QueuedConnection);
    
        engine.load(url);
        QString test = "";
    
    
        Receiver receiver ;
       receiver.initSocket();
    
        return app.exec();
    }
    
    
    
    


  • I don't have time to help your specific example (sorry). However, I'd suggest looking at the functional example projects in Qt Creator. Look for something like "fortune server" and "fortune client" there's a couple examples that should get you right on track.


  • Lifetime Qt Champion

    @Eli_a_n said in UDP packets received only the first time.:

    i only receive the udp packets the first time i send them, all after that aren't shown anymore

    What does this mean exactly? Do you stop and start your app and then it does not work?



  • @jsulm Hi,

    So, i start the app, i send an udp packet from another terminal in the local network, i receive and display it in qt, everything is fine so far. With the app still running, and without changing anything, i send the second packet from the same terminal in the local network and i don't receive it (or it just doesn't display it) in qt.

    It's absolutely weird.

    What are your thoughts?



  • @Eli_a_n

            processPendingDatagrams();
            connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection);
    

    Probably irrelevant, but I'd get rid of the first processPendingDatagrams();, outside of the connect(SIGNAL(readyRead())), just in case it influences what you see. There is no need for it in your test problem, is there?

    m_udpSocket->bind(QHostAddress::AnyIPv4, 4210);
    

    bind() returns a bool. If you don't c heck it, maybe the whole binding isn't working....

    void QAbstractSocket::errorOccurred(QAbstractSocket::SocketError socketError): if you don't slot this signal, how would you know if there is some error?

    These are the sort of things I would do if developing and I had a problem.



  • @JonB thanks for the heads up

    Here is what i did:

    Receiver::Receiver(QObject *parent)
        : QObject(parent)
    {
        m_status = "--";
    
        m_udpSocket = new QUdpSocket(this);
            if(m_udpSocket->bind(QHostAddress::AnyIPv4, 4210))
                qDebug() << "Bind succesfull on port 4210" ;
            else
                qDebug() << "Bind failed on port 4210";
    
        
            connect(m_udpSocket, SIGNAL(readyRead()), this,
                    SLOT(processPendingDatagrams()), Qt::QueuedConnection);
            connect(m_udpSocket, SIGNAL(disconnected()), this,
                    SLOT(Disconnected()));
            connect(m_udpSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
                [=](QAbstractSocket::SocketError socketError){ qDebug() << "socket error " << socketError; });
    }
    
    void Receiver::processPendingDatagrams()
    {
        while (m_udpSocket->hasPendingDatagrams()) {
    
            QByteArray datagram;
    
            QHostAddress sender;
            quint16 senderPort;
        qDebug() << "2 ";
            datagram.resize(m_udpSocket->pendingDatagramSize());
            m_udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
    
             qDebug() << "Message from: " << sender.toString();
             qDebug() << "Message port: " << senderPort;
             qDebug() << "Message: " << datagram;
    
        }
    }
    
    void Receiver::ReceiveData ()
      {
         qDebug() <<"Socket received data...";
      }
    
      void Receiver::Disconnected ()
      {
        qDebug() <<"Socket got disconnected...";
      }
    
      void Receiver::Error (QAbstractSocket::SocketError error)
      {
         qDebug() <<"Socket error " << error;
      }
    

    but i get o disconnect message nor an error message:

    pi@raspberrypi:~/RTCs/bin $ ./RTCs
    QML debugging is enabled. Only use this in a safe environment.
    
    Bind succesfull on port 4210
    Message from:  "192.168.68.111"
    Message port:  52848
    Message:  "test\r\n"
    
    

  • Lifetime Qt Champion

    Hi,

    Did you check the examples linked in the details of the QUdpSocket class ?

    Compare them to your client and server code to spot the differences.

    On a side note, you should move all your connection to the new style so you won't have any runtime surprises.



  • @Eli_a_n said in UDP packets received only the first time.:

    i only receive the udp packets the first time i send them, all after that aren't shown anymore.

    One thing. I've seen a fair amount of user questions in this forum. If I come over to your place and find that actually you are only sending one packet, will you give me $5? :) Please verify multiple packets really are being sent...!



  • @JonB :)) that would be funny but i'm actually sending the packets using software called UDP - Sender/Reciever from Microsoft Store. To make sure that i have no problem with firewall or anything like that i made a simple app in python and i'm getting all the packets just fine there. So there is a problem with the QT app.

    I will try to investigate some more.

    By the way, not sure if it makes any difference but i'm running the QT app on raspberry pi.

    Regards



  • Not sure i'm loading the class correctly.

    in my main.cpp i do :

    Receiver *rcv = new Receiver();
    rcv->initSocket();
    

    where initSocket is:

    void Receiver::initSocket(){
        QByteArray Data;
            Data.append("Hello from UDP");
    
            m_udpSocket = new QUdpSocket(this);
                if(m_udpSocket->bind(QHostAddress::AnyIPv4, 4210))
                    qDebug() << "Bind succesfull on port 4210" ;
                else
                    qDebug() << "Bind failed on port 4210";
    
    
                connect(m_udpSocket, SIGNAL(readyRead()), this,
                        SLOT(processPendingDatagrams()), Qt::QueuedConnection);
                connect(m_udpSocket, SIGNAL(disconnected()), this,
                        SLOT(Disconnected()));
                connect(m_udpSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
                    [=](QAbstractSocket::SocketError socketError){ qDebug() << "socket error " << socketError; });
    
            // Sends the datagram datagram
            // to the host address and at port.
            // qint64 QUdpSocket::writeDatagram(const QByteArray & datagram,
            //                      const QHostAddress & host, quint16 port)
    
    //             m_udpSocket->writeDatagram(Data, QHostAddress::LocalHost, 4210);
    
    }
    

    shoud i start the Receiver class in a thread or something?

    using the debuger, after i receive the first packet, using the "step over" i end up back in the main.cpp at the line :
    return app.exec();

    Is this normal ?


  • Lifetime Qt Champion

    Please simply use the examples from Qt to see if it works for you as @SGaist already told you. There we know the code exactly and we know they're working fine for us. We don't know your program and you don't provide a minimal, compilable example so we can't see what else you're doing.

    See e.g. https://doc.qt.io/qt-5/qtnetwork-broadcastreceiver-example.html and https://doc.qt.io/qt-5/qtnetwork-broadcastsender-example.html



  • @Christian-Ehrlicher Hi, what do you mean? in my initial post i provided the main.cpp and both full receiver files, what else would you need? Anyway,

    I loaded the broadcast receiver project you suggested and currently i have the following cases:

    1. Launching from one terminal the broadcast receiver app you suggested and from another terminal using netcat -u 127.0.0.1 45454 and netcat -u 192.168.68.107 45454 (which is the IP of my raspberry pi on the local network) i get all the messages that i'm sending

    2. without changing anything in the case 1 above, i'm sending the packets from:

    • Ubuntu terminal - netcat -u 192.168.68.107 45454
    • Windows UDP - Sender/receiver application
    • Packet sender application on windows

    From none of the apps listed above manage to receive the packets

    1. Closing the broadcast receiver app and opening a simple python udp receiver i can receive the packets from all mentioned at case 2

    2. Closing the python receiver app and opening my initial application i can receive only the first packet sent.

    Any thoughts ?

    Regards



  • OK, so i don't know exactly why but I got it working.

    I believe that the following were the problems:

    m_udpSocket->bind(QHostAddress::AnyIPv4, 4210) 
    **instead of** 
    udpSocket->bind(45454, QUdpSocket::ShareAddress); as mentioned in the broadcast receiver example
    
    
    connect(m_udpSocket, &QUdpSocket::readyRead,  this, &Receiver::processPendingDatagrams);
    **instead of** 
    connect(m_udpSocket, SIGNAL(readyRead()), this,  SLOT(ReceiveData()), Qt::QueuedConnection); what i used in my initial application when posting for help
    
        while (m_udpSocket->hasPendingDatagrams()) {
            datagram.resize(int(m_udpSocket->pendingDatagramSize()));
            m_udpSocket->readDatagram(datagram.data(), datagram.size());
    
            qDebug() << "Message: " << datagram.constData();
        }
    
    **instead of** 
    
    while (m_udpSocket->hasPendingDatagrams()) {
            QByteArray datagram;
    
            QHostAddress sender;
            quint16 senderPort;
        qDebug() << "2 ";
            datagram.resize(m_udpSocket->pendingDatagramSize());
            m_udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
    
    
             qDebug() << "Message from: " << sender.toString();
             qDebug() << "Message port: " << senderPort;
             qDebug() << "Message: " << **datagram;**
    
    //as per my initial program
        }
    

    Thank you all for all your involvement and support
    Regards
    Elian N.


Log in to reply