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++.
Figure 1. Actual Output of sending packets over TCP
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 socketsend()
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
-
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 callreadLine()
instead ofreadAll()
(remember to do that in a loop as long ascanReadLine()
returns true).This is a very simple protocol, but I've used it sucessfully with serial ports also.
Regards
-
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 sortFor 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.
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 aQByteArray
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.