QTcpSocket - multiple sends received at the same time, what is the best solution ?



  • I have send data continuously over QTcpSockets using QT C++. When I receive data by readAll() , multiple packets received at the same time (Figure 1) . Expected output is shown at Figure 2. I want to learn what is the best solution for this situation in QT C++.

    0_1533207595509_Screenshot-1.png

    Figure 1. Actual Output of sending packets over TCP

    0_1533207678444_Screenshot-2.png

    Figure 2. Expected Output of sending packets over TCP

    In Server Side :

    Producer.h

    #ifndef PRODUCER_H
    #define PRODUCER_H
    
    #include <QObject>
    #include <QtNetwork>
    
    static int counter = 1;
    
    class Producer : public QObject
    {
        Q_OBJECT
    public:
        explicit Producer(QObject *parent = 0);
    
    signals:
    
    public slots:
        void updateServerProgress(qint64);
        void acceptConnection();
        void startTransfer();
    private:
        QTcpServer tcpServer;
        QTcpSocket *tcpServerConnection;
         QByteArray byteArray;
    };
    
    #endif // PRODUCER_H
    

    Producer.cpp

    #include "producer.h"
    
    Producer::Producer(QObject *parent) :
        QObject(parent)
    {
        tcpServer.listen(QHostAddress::LocalHost,12345);
        if(!tcpServer.isListening() && !tcpServer.listen())
        {
            qDebug() << "Unable to start " << tcpServer.errorString();
        }
        connect(&tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));
    }
    
    void Producer::acceptConnection()
    {
        tcpServerConnection = tcpServer.nextPendingConnection();
    
        qDebug() << "Connected..";
        startTransfer();
        connect(tcpServerConnection,SIGNAL(bytesWritten(qint64)),this , SLOT(updateServerProgress(qint64)));
    
    }
    void Producer::startTransfer()
    {
        tcpServerConnection->write(byteArray.setNum(0));
          qDebug() << "Sent : " << 0 ;
    }
    void Producer::updateServerProgress(qint64 numPack)
    {
        QElapsedTimer timerProduce ;
    
        tcpServerConnection->write(byteArray.setNum(counter));
        qDebug() << "Sent : " << counter ;
        ++counter;    
    }
    

    In Client Side :

    Consumer.h

    /#ifndef CONSUMER_H
    #define CONSUMER_H
    
    #include <QObject>
    #include <QtNetwork>
    
    class Consumer : public QObject
    {
        Q_OBJECT
    public:
        explicit Consumer(QObject *parent = 0);
    
    signals:
    
    public slots:
        void updateClientProgress();
    
    private:
        QTcpSocket tcpClient;
        QByteArray byteArray;
    
    };
    
    #endif // CONSUMER_H
    

    Consumer.cpp

    #include "consumer.h"
    
    Consumer::Consumer(QObject *parent) :
        QObject(parent)
    {
        connect(&tcpClient, SIGNAL(readyRead()),this,SLOT(updateClientProgress()));
        tcpClient.connectToHost(QHostAddress::LocalHost,12345);
    }
    void Consumer::updateClientProgress()
    {
       
        qDebug() << "Read All : " << tcpClient.readAll();
    
    }
    
    


  • @Ayse
    Are you saying: you expect to receive sent packets separately at the receiving side? TCP/IP is a "continuous streaming" protocol, receivers don't receive/see the low-level TCP packet boundaries or the individual socket send()s, and are not intended to. You won't get at individual TCP packets from sockets.

    Depending on what you want, if you are in charge of the server code you can change your high-level protocol to insert some kind of your own "packet separator" between its send() calls which the client can recognise and deal with, if that is what you're aiming for.



  • Hi,

    I haven't done anything with QTcpSocket yet but it is likely that your producer is producing at a different rate than the consumer is consuming. You are calling readAll which will read everything available. There are other methods which you can call which allow you to define the number of bytes to read.

    The first thing I would do is see if you can get your desired behavior by adding "\r\n" and slowing down the producer with a QThread::msleep() or something of the sort.

    -Shawn


  • Qt Champions 2017

    Hi @Ayse,

    @JonB is right, you have to define your own protocol.

    If you're transmitting ASCII data (like it seems), the easiest way would be to append \n after each of your "packets". On the receiver side, you can then call readLine() instead of readAll() (remember to do that in a loop as long as canReadLine() returns true).

    This is a very simple protocol, but I've used it sucessfully with serial ports also.

    Regards



  • @aha_1980 It is really helpful for me. I tried it and it is successful. Thank you for your solution.

    Regards..



  • @MrShawn

    I haven't done anything with QTcpSocket yet but it is likely that your producer is producing at a different rate than the consumer is consuming.
    and slowing down the producer with a QThread::msleep() or something of the sort

    For the record, it may be important for the OP to understand that this is not the way TCP/IP works. Unlike, say, UDP, TCP does not "lose" data because the consumer cannot keep up with the producer. The producer will eventually be blocked if no more data can be sent, but that's it. So slowing down the producer should not produce anything useful.



  • @aha_1980 I wonder how can I generate a packet with packet number, data(double array) , data length and send/receive this packet over QTcpSockets , I search this kind of data transmission but I can not handle in code.

    0_1533297423133_Adsız.png

    Figure 3. Packet Type

    Regards..



  • @Ayse
    http://doc.qt.io/qt-5/qiodevice.html#write or http://doc.qt.io/qt-5/qiodevice.html#write-2 let you write arbitrary bytes of whatever length down the socket. You can use them a bit at time to write parts of your structure, or fill a QByteArray and send in one go. You'll have to put your numeric stuff into a byte array before you can send it. And if you know anything about networks & byte ordering, you'll know you have to be careful which order you do that in, depending on what order the other size is expecting and/or whether client & server have same machine architecture.

    Your "packet structure" still looks a bit like you're trying to do stuff at the TCP/IP level, which is not what sockets will allow, but maybe not, I leave that to you to understand.


Log in to reply
 

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