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

QUdpSocket does not trigger ReadyRead signal



  • I am reading and sending QImage with QUdpSocket in a for loop but I can't get the QImages because readyRead() signal doesn't get emmited. Here is my code:

    udpsocket.h

    #ifndef UDPSOCKET_H
    #define UDPSOCKET_H
    
    #include <QObject>
    #include <QUdpSocket>
    
    #include "camera.h"
    
    class UDPSocket : public QObject
    {
        Q_OBJECT
    public:
        explicit UDPSocket(QObject *parent = nullptr);
        void sendFrame(QImage frame);
    
    signals:
    
    
    public slots:
        void readyRead();
    
    private:
    
        QUdpSocket *socket;
    
    
    };
    
    #endif // UDPSOCKET_H
    
    

    udpsocket.cpp

     #include "udpsocket.h"
    #include <QDebug>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <unistd.h>
    #include <udpsocket.h>
    #include <QBuffer>
    #include <QDebug>
    #include <QImage>
    #include <QImageWriter>
    
    #define XRES 640
    #define YRES 480
    #define SIZE 640*480*3
    
    
    
    UDPSocket::UDPSocket(QObject *parent) : QObject(parent)
    {
    
        socket = new QUdpSocket(this);
        bool deneme= socket->bind(QHostAddress::LocalHost,1234);
        if(deneme)
            qDebug()<<"binded";
        connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
    
    }
    
    
    void UDPSocket::sendFrame(QImage image)
    {
        qDebug()<<"will send";
    
        QBuffer buffer;
        QImageWriter writer(&buffer,"bmp");
        writer.write(image);
        QByteArray data;
        data.append(buffer.data());
        socket->writeDatagram(data,QHostAddress::Broadcast,1234);
    
    
        qDebug()<<"sent";
    
    
    }
    
    void UDPSocket::readyRead()
    {
        qDebug()<<"readyread";
        QByteArray buffer;
        buffer.resize(socket->pendingDatagramSize());
    
        QHostAddress sender;
        quint16 senderPort;
    
        socket->readDatagram(buffer.data(),buffer.size(),&sender,&senderPort);
    
    
        std::ostringstream stream;
        stream << "frames/" << qrand() << ".bmp";
        std::string new_string = stream.str();
        std::ofstream image;
        image.open(new_string);
        image << "P6\n" << XRES << " " << YRES << " 255\n";
    
        image.write(buffer.data(), SIZE);
        image.close();
        qDebug()<<"image arrived";
    }
    

    main.cpp

    #include <QCoreApplication>
    #include <camera.h>
    #include <QThread>
    #include <QDebug>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <unistd.h>
    #include <udpsocket.h>
    
    #include <QPixmap>
    
    
    #define XRES 640
    #define YRES 480
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        UDPSocket udpObject;
    
        QImage *image;
    
         Camera camera("/dev/video0", XRES, YRES);
    
            for(int i=0; i<10; i++)
            {
               auto frame = camera.frame();
               QThread::sleep(0.0416);
               image = new QImage(frame.data,XRES,YRES,QImage::Format_RGB888);
               udpObject.sendFrame(*image);
    
    
    
    }
    
    
        return a.exec();
    }
    
    

    When I run this code I see

    binded
    will send
    sent
    

    10 times (because of for loop in main.cpp) and when I debug readyread() doesn't even run.

    How can I fix this code so I can recieve the images I sent ? Should I use connectToHost instead of bind() ?

    Note:camera.h is my class that I use to read images from camera and probably has nothing to do with error.


  • Lifetime Qt Champion

    Hi,

    Are you trying to send and receive the image using the exact same socket ?



  • @SGaist In main.cpp I create the UDPSocket object outside the for loop then use the same object to access thesendFrame(QImage frame); function to send the sockets inside the loop . So I guess I use the same socket.


  • Lifetime Qt Champion

    Then show what you are doing.

    From what you wrote, you don't even have an event loop running hence not signals/slots working.

    Also, why are you trying to use UPD to send data from your application back to the same application ?



  • @SGaist I already posted almost all of my code? What do you mean "show what you are doing?"
    I am sending/recieving on same PC to test if I can so later I can implement it for different PC's. Since Im newbie I dont know much about event loops can you show some example?


  • Qt Champions 2019

    @onurcevik Can you show your main.cpp?



  • @jsulm I edited and added main.cpp to my question.


  • Qt Champions 2019

    @onurcevik A loop with sleep() inside (before starting event loop) and you expect this to work? It will not. See what @SGaist wrote.



  • @jsulm @SGaist Sorry for my noob mistakes. I searched event loop in QT but I couldn't find how to implement it. Can you help me with that ? Should I use Threads ?


  • Qt Champions 2019

    @onurcevik

    return a.exec();
    

    this starts the event loop. No need for threads. Use asynchronous nature of QUdpSocket instead. You should take a look at one of the example applications for networking.



  • @jsulm I deleted sleep and for loop it still did not work. I did take a look couple of examples even tried to run it. A pinpoint to what wrongs with my code would be really helpful. Since removing sleep and for did not work either.

    Edit: I will switch to QWidget application and try to send through a button click.


  • Lifetime Qt Champion

    Hi @onurcevik,

    • On which platform are you?
    • Which Qt version do you use?
    • Do you have multiple network adapters in your computer?

    Regards



  • @aha_1980

    • I am on Kubuntu
    • I use Qt Creator 4.6.2 Based on Qt 5.11.1 (GCC 8.1.0, 64 bit)
    • I only have 1 modem.

  • Lifetime Qt Champion

    @onurcevik

    Can you please post the output of ifconfig -a?

    It is likely that your packet is not even send out. You can check that with Wireshark.

    Edit:

    I use Qt Creator 4.6.2 Based on Qt 5.11.1 (GCC 8.1.0, 64 bit)

    That is the Creator version, not the Qt version I asked for.



  • @aha_1980

    That is the Creator version, not the Qt version I asked for.

    I use Qt Creator 4.6.2 Based on Qt 5.11.1 (GCC 8.1.0, 64 bit)

    QT version is next to the QT Creator Version which is 5.11.1

    the output of ifconfig -a :

    enp27s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.2.44  netmask 255.255.255.0  broadcast 192.168.2.255
            inet6 fe80::a98d:26da:2afd:3299  prefixlen 64  scopeid 0x20<link>
            ether 00:d8:61:15:7d:b8  txqueuelen 1000  (Ethernet)
            RX packets 37659  bytes 41459688 (41.4 MB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 27301  bytes 2684010 (2.6 MB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10<host>
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 1963  bytes 180145 (180.1 KB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 1963  bytes 180145 (180.1 KB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    

    @aha_1980 said in QUdpSocket does not trigger ReadyRead signal:


  • Lifetime Qt Champion

    @onurcevik said in QUdpSocket does not trigger ReadyRead signal:

    QT version is next to the QT Creator Version which is 5.11.1

    That is the Qt version Creator is built with, which is not necessarily the version you are using to compile your program.

    From you ifconfig I see, that there is only one physical interface., so bind should select the correct one.

    Please check with wireshark that the packet is sent out.


  • Lifetime Qt Champion

    Just for the sake of simplification, did you take a look at the examples linked in the QUdpSocket documentation ?

    Thinking about:

    Broadcast Sender
    Broadcast Receiver
    Multicast Sender
    Multicast Receiver



  • @aha_1980 I now realized that I can't even send the socket due to large size which is 1 mb. Do you know how can I divide it into chunks of bytes ? Or should I create new topic?


  • Lifetime Qt Champion

    What exactly is the goal of your application ?



  • @SGaist I want to take pictures from camera then send and recieve them continuously in order to implement a real time video streaming application. The reason I am sending images instead of video is because I will later work on image processing. I realized that image size is too big for this which is 6404803 BYTES. But I also can't switch to TCP because I need the speed of UDP.



  • Ok,
    I apologize to mother tongue people for my English, I know, it isn’t good
    Anyway, If I have understood correctly there is a limit of 1Mb, but limit apart, to do this I always do:

    The server application

    • Send a header with a fixed size and with the following information: a security key (to recognise a my flow), data size, …. and then send data
    • You can get and save a pointer of data from QbyteArray by “data” function
    • With a loop I send few pieces of data ( < 1Mb) by writeDatagram, it is easy, all you need to do you have to use an index to move on the data pointer

    The client application:

    • When it will receive your header and recognise it, it will know data size too
    • read all data that will receive and reassemble the all image

    For me UDP is a good choice.

    I hope to help you.



  • @CP71 said in QUdpSocket does not trigger ReadyRead signal:

    The client application:

    • When it will receive your header and recognise it, it will know data size too
    • read all data that will receive and reassemble the all image

    For me UDP is a good choice.

    How do you manage to "read all data" corresponding to "it will know data size" given that you're using UDP?


  • Lifetime Qt Champion

    If you want to stream videos then you should follow the standards currently used to minimise bandwidth usage while keeping image quality.

    As for video processing, you should give more information about what you want to do.



  • @JonB Ok,
    you are right, I think to know what you want to say, all depend of kind of application you are doing.
    You believe me, I done real-time application with UDP and they work well.
    Ok, TCP is more safety but UDP is faster, I’m not game developer but as far as I know more games are based on UDP, because it is faster.
    It's obvious, the client must check the integrity of data and discard the bad data, e.g by checksum.
    I don’t know the goal of @onurcevik, but if a frame video is delayed or lost it will be discarded.
    All depend if you want to prefer the speed or the quality of information therefore what the client application must do.



  • @CP71
    You may well know more than I. But as I understand it UDP can happily lose any packets at the client, that's the point of it. By splitting your datagrams like you said if one does not arrive what happens at the client, it seems to me that protocol just won't work? Maybe in your "real-world" apps none get missed, I don't actually have experience, I am just interested/concerned. :)



  • @JonB Don’t worry, I happy to communicate with you, so I’m training in English that is useful for me ;).
    I don’t know if I can post a link to other site or forum, so I avoid.
    I don’t say UDP is better than of TCP, I say that depend of your goal of application, each protocol has its scope.
    For me, I would use UDP for stream video, especially if the client must be only show the image.
    But it is only my idea.


Log in to reply