How to properly work with multiple QUdpSockets in Qt in a single Application

1k views Asked by At

I have created a server and a client class, which are using UDP protocol. In my Application I have Instantiated 4 objects of Server and 4 objects of client with different Ports.

The problem is I have send data to 4 servers from 4 clients in the same time, But each server Receives it's data only when previous server has finished it's work...

why this is happennig?

this is my code:

Main:

std::thread thread;

client cl1(4235),cl2(4245),cl3(4255),cl4(4265);

void handler()
{
    while(1){

        cl1.SendData("HI1",4230);
        cl2.SendData("HI2",4240);
        cl3.SendData("HI3",4250);
        cl4.SendData("HI4",4260);
        std::this_thread::sleep_for(std::chrono::seconds(50));
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    server s1(4230);
    server s2(4240);
    server s3(4250);
    server s4(4260);
    thread = std::thread(handler);
    return a.exec();
}

Server Class:

class server : public QObject
{
    Q_OBJECT
public :
    server(int port)
    {
        this->port = port;
        udpSocket = new QUdpSocket();
            udpSocket->bind(QHostAddress::LocalHost, port);

            connect(udpSocket, SIGNAL(readyRead()),
                    this, SLOT(readPendingDatagrams()));
    };
   public  slots:
    void readPendingDatagrams()
    {
        while (udpSocket->hasPendingDatagrams()) {
            QByteArray datagram;
            datagram.resize(udpSocket->pendingDatagramSize());
            QHostAddress sender;
            quint16 senderPort;

            udpSocket->readDatagram(datagram.data(), datagram.size(),
                                    &sender, &senderPort);

            //processTheDatagram(datagram);
            QDateTime dateTime;
            dateTime = dateTime.currentDateTime();
            qDebug() << QString::number(dateTime.time().hour()).rightJustified(2, '0') + ":" +//hour
                        QString::number(dateTime.time().minute()).rightJustified(2, '0') + ":" +//minute
                        QString::number(dateTime.time().second()).rightJustified(2, '0');//seconds
            qDebug() << "\t\tdata received from:" << sender.toString() <<":"<<senderPort << "  data:" << datagram;


            std::this_thread::sleep_for(std::chrono::seconds(5));

            qDebug() << QString::number(dateTime.time().hour()).rightJustified(2, '0') + ":" +//hour
                        QString::number(dateTime.time().minute()).rightJustified(2, '0') + ":" +//minute
                        QString::number(dateTime.time().second()).rightJustified(2, '0');//seconds
            qDebug () << "Sending Response";
            udpSocket->writeDatagram(("HI back from" + QString::number(port)).toUtf8(),sender,senderPort);
        }
    };

private:
    QUdpSocket * udpSocket;
    int port;
};

Client Class:

class client : public QObject
{
    Q_OBJECT
   public:
    client(int port) {
        this->port = port;
        udpSocket = new QUdpSocket();
            udpSocket->bind(QHostAddress::LocalHost, port);

            connect(udpSocket, SIGNAL(readyRead()),
                    this, SLOT(readPendingDatagrams()));
    }
    void SendData(QString Data,int serverport)
    {
        QDateTime dateTime;
        dateTime = dateTime.currentDateTime();


        udpSocket->writeDatagram(Data.toUtf8(),QHostAddress::LocalHost,serverport);
        qDebug() << QString::number(dateTime.time().hour()).rightJustified(2, '0') + ":" +//hour
                    QString::number(dateTime.time().minute()).rightJustified(2, '0') + ":" +//minute
                    QString::number(dateTime.time().second()).rightJustified(2, '0')//sec
                 << "\tclient : " <<port << " sending data to server:" << Data;
    }
   public  slots:
    void readPendingDatagrams()
    {
        while (udpSocket->hasPendingDatagrams()) {
            QByteArray datagram;
            datagram.resize(udpSocket->pendingDatagramSize());
            QHostAddress sender;
            quint16 senderPort;

            udpSocket->readDatagram(datagram.data(), datagram.size(),
                                    &sender, &senderPort);

            //processTheDatagram(datagram);
            QDateTime dateTime;
            dateTime = dateTime.currentDateTime();
            qDebug() << QString::number(dateTime.time().hour()).rightJustified(2, '0') + ":" +//hour
                        QString::number(dateTime.time().minute()).rightJustified(2, '0') + ":" +//minute
                        QString::number(dateTime.time().second()).rightJustified(2, '0');//seconds
            qDebug() << "\t\tclient : " <<port << " data received from:" << sender.toString() <<":"<<senderPort << "  data:" << datagram;
        }
    }

private:
    QUdpSocket * udpSocket;
    int port;
};

this is My output data:

"18:50:07"  client :  4235  sending data to server: "HI1"
"18:50:07"  client :  4245  sending data to server: "HI2"
"18:50:07"  client :  4255  sending data to server: "HI3"
"18:50:07"  client :  4265  sending data to server: "HI4"
"18:50:07"
        data received from: "127.0.0.1" : 4235   data: "HI1"
"18:50:07"
Sending Response
"18:50:12"
        data received from: "127.0.0.1" : 4245   data: "HI2"
"18:50:12"
Sending Response
"18:50:17"
        data received from: "127.0.0.1" : 4255   data: "HI3"
"18:50:17"
Sending Response
"18:50:22"
        data received from: "127.0.0.1" : 4265   data: "HI4"
"18:50:22"
Sending Response
1

There are 1 answers

4
smacker On
std::this_thread::sleep_for(std::chrono::seconds(5)); 

is blocking your current thread. And looking at your main(), this also blocks the main application thread. Therefore, your application will not receive messages from the OS about incoming packets. You should not use sleep functions inside the slots connected to readyRead signals, if you want to process the data in parallel.