QUdpSocket readyRead never emitted



  • Hey guys,

    I am new to QT and trying to do some network stuff in C++.
    I am receiving UDP packets for an external program very second and try to catch them using a QUdpSocket.

    First I built an example application to test the code and it worked fine, the specified method was called when the socket picked up a udp packet.

    void networka::test()
    {
        QByteArray datagram;
        while(udp_socket->hasPendingDatagrams())
        {
            datagram.resize(int(udp_socket->pendingDatagramSize()));
            udp_socket->readDatagram(datagram.data(), datagram.size());
            std::cout << "receive" << std::endl;
        }
    }
    
    void networka::run()
    {
        udp_socket = new QUdpSocket();
        if(!udp_socket->bind(QHostAddress::Any, 851, QAbstractSocket::BindFlag::ShareAddress))
        {
            std::cout << "bind error" << std::endl;
        }
    
        if(udp_socket->state() == QUdpSocket::BoundState)
        {
            std::cout << "server bound" << std::endl;
        }
    
        QObject::connect(udp_socket, &QUdpSocket::readyRead, [=]()
        {
            test();
        });
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication ab(argc, argv);
    
        networka aa;
        aa.run();
    
        return ab.exec();
    }
    

    Then I integrated the code from my sample project in our application, but the readReady signal is never emitted

    void EthProtocolDevice::open(std::string targetAddress, uint16_t port, EthernetProtocol::Protocol protocol)
    {
             c_udpSocket = new QUdpSocket();
            QObject::connect(c_udpSocket, &QUdpSocket::readyRead, [=]()
            {
                onUdpSocketReceive();
            });
    
            if(!c_udpSocket->bind(QHostAddress::Any, port, QAbstractSocket::BindFlag::ShareAddress))
            {
                std::cout << "[EthProtocolDevice::open] udp sockedt failed to bind to port " << port << std::endl;
                result = false;
            }
        }
    }
    
    void EthProtocolDevice::onUdpSocketReceive()
    {
        QByteArray datagram;
        QHostAddress remoteHost;
        quint16 remotePort;
        while(c_udpSocket->hasPendingDatagrams())
        {
            datagram.resize(int(c_udpSocket->pendingDatagramSize()));
            c_udpSocket->readDatagram(datagram.data(), datagram.size(), &remoteHost, &remotePort);
            
            if((c_protocol == EthernetProtocol::Protocol::epGNLog) /*TODO: && getTransmitEnabled()*/)
            {
                if(datagram.startsWith(UDP_MOIN_MESSAGE.c_str()))
                {
                    c_udpSocket->writeDatagram(UDP_MOIN_MESSAGE.c_str(), remoteHost, remotePort);
                }
            }
        }
    }
    


  • do you ever call writeDatagram?

    P.S.
    if you call new you always have to make sure you are handling the delete. Pass a parent to the socket



  • @VRonin
    thanks for your reply
    No, I am just listening, but that shouldn´t be the problem because in my standalone example all works fine.
    Thanks for the tipp, but I delete the socket in the destructor, so I think the parent is not necessary?



  • No, I am just listening, but that shouldn´t be the problem

    What I'm saying is that in the code you posted there is no trace of you sending something to the socket so it's only natural it doesn't receive anything

    @ZF__ said in QUdpSocket readyRead never emitted:

    so I think the parent is not necessary?

    Think what happens if you call open() or run() twice



  • @VRonin
    I am sending data to the socket and in the example program (first piece of code) the signal is emitted so it must be an issue in the second piece of my code.
    I have also checked with wireshark, there is data it should pick up. When I call the syncronous receiveDatagram the data is received.

    Yeah, thats true.



  • @VRonin said in QUdpSocket readyRead never emitted:

    Think what happens if you call open() twice

    valid point, but I don't think, that simply giving QUdpSocket a parent isn't suffiecnt in this case.

    The old Socket still is in the background, listening and fireing Signals(ReadyRead) in this case resulting in fals/multiple calls of the slot.

    This case actually needs a full delete management. E.g:

    //Setting/Initalizing member with 0 
    QUdpSocket c_udpSocket = 0;
    
    ....
    
    if(c_udpSocket){
        c_udpSocket->deleteLater();
        c_udpSocket = Q_NULLPTR;
    }
    
    c_udpSocket = new QUdpSocket();
    ....
    
    


  • Do you have an event loop running in the second snippet? are you blocking it somehow (e.g. an infinite loop)?



  • @J.Hilk
    I think so too, thanks for your snippet!

    @VRonin
    Yes I have the eventloop running, but I am not sure if I implemented it the right way.
    Currently I am using wxWidgets as Framework for the UI and some Internals, but I want to replace it with Qt.
    My softwareproject is quiet big, so I thought about replacing wxWidgets step by step.

    I just moved the Qt eventloop in the wxWidgets OnRun function, which seems to be the "main" in wxWidgets (https://forums.wxwidgets.org/viewtopic.php?t=5708)

    int DataGeneratorMain::OnRun()
    {
        QCoreApplication a(argc, argv);
    
         a.exec();                         //QT eventloop
         //wxApp::OnRun();       //wxWidgets eventloop
        
        return 0;
    }
    


  • Any suggestions?



  • @ZF__ said in QUdpSocket readyRead never emitted:

    QCoreApplication a(argc, argv);

    What are argc and argv here? it should not compile like that.

    there's nothing obvious in the code that might cause the problem. Are you still running a wxWidgets event loop as well?



  • @VRonin

    argc and argv are declared through the wxWidgets framework.

    No, I commented out the wxWidgets eventloop, because I wanted to run the QT eventloop instead.
    Can you tell me how to run two eventloops at one time? I don´t know how, because both calls to start the loop are blocking.



  • @ZF__ said in QUdpSocket readyRead never emitted:

    Can you tell me how to run two eventloops at one time? I don´t know how, because both calls to start the loop are blocking.

    Correct, one blocks the other, that's why I asked, if you had a wxWidgets loop the Qt one would not be able to process slots



  • @VRonin

    Can I start the eventloop in a thread?

    Edit: I have found out that ANY other signal is trigged (bytesWritten for example), just the readyRead signal is not working.
    Also I found out that redyRead gets emitted once each time I call waitForReadyRead()



  • @ZF__ said in QUdpSocket readyRead never emitted:

    @VRonin

    Can I start the eventloop in a thread?

    Edit: I have found out that ANY other signal is trigged (bytesWritten for example), just the readyRead signal is not working.
    Also I found out that redyRead gets emitted once each time I call waitForReadyRead()

    someone can help me?



  • @ZF__
    QAbstractSocket also provides signals bytesAbailable and bytesWritten..
    First i suggest you to use qthreads..

    networka aa;
    QThread * td = new Thread;
    aa.moveToThread(td);
    td.start();
    

    Create udpsocket in networka and connect signals such as bytesAvailable, disconnected and other signals as below in networka

    QUDPSocket * udpSocket;
    // other connection related stuff...
    Connect(udpSocket,SIGNAL(bytesAvailable()),this,SLOT(readData()));
    // connect other signals ...
    
    

    implement slot in networka something like

    void readData(){
       QByteArray ary = udpSocket.readAll();
       // ary contains all data thats read...
    }
    

    this way you can get rid of while loop and corresponding slots will be connected on respective signals..
    i.e., when bytes are available in socket, readData Slot will be called and you read data...

    PS: signals what i mentioned above may not be exact.. please check documentation for exact syntax.


Log in to reply
 

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