How to receive data in order from TCP server ?
-
Hello,
I have a TCP client application that send and receive data successfully. First I send read request with packet that includes command id and data to server application. If server side processes this packet successfully, it sends a response packet that includes same command id and expected data.
When I receive data in readyRead slot function, I set the related points in GUI ((assume I have value1, value2 variables defined in widget.h)):void Widget::readSocket() { QByteArray buffer; buffer = tcpSocket->readAll(); // Some parsing operation to extract data from buffer to set value1 // ui->labelValue1->setText(QString::number(value1)); }
To read all incoming data periodically (on every 1 second), I want to implement update function in QTimer's timeout function like this :
void Widget::update() { readValue1(); ui->labelValue1->setText(QString::number(value1)); readValue2(); ui->labelValue2->setText(QString::number(value2)); . . . }
To read values sequentially, I am planning to implement a blocking structure by using waitForReceivedData(int timeoutInMs) function. If the expected value is observed in determined timeout period, I can set a flag and proceed to next reading operation :
void Widget::update() { readValue1(); waitForReceivedData(100); ui->labelValue1->setText(QString::number(value1)); readValue2(); waitForReceivedData(100); ui->labelValue2->setText(QString::number(value2)); . . . }
The thing is, I can receive different values externally besides update() function(with a push button) and these values may interfere in readSocket() function. Therefore, I may read wrong values in update() function.
I need to receive data in order in readyRead() function so that I can read true values in both update() function or other external events. When I researched about this, I encountered topics such as threads, queue etc. Maybe I can use a kind of lock mechanism or queue by using command id in packet that I send & receive.
What is the proper way to handle this ? I am kind of new to Qt so I will be very appreciated if you could help me
Regards
-
Hello,
I have a TCP client application that send and receive data successfully. First I send read request with packet that includes command id and data to server application. If server side processes this packet successfully, it sends a response packet that includes same command id and expected data.
When I receive data in readyRead slot function, I set the related points in GUI ((assume I have value1, value2 variables defined in widget.h)):void Widget::readSocket() { QByteArray buffer; buffer = tcpSocket->readAll(); // Some parsing operation to extract data from buffer to set value1 // ui->labelValue1->setText(QString::number(value1)); }
To read all incoming data periodically (on every 1 second), I want to implement update function in QTimer's timeout function like this :
void Widget::update() { readValue1(); ui->labelValue1->setText(QString::number(value1)); readValue2(); ui->labelValue2->setText(QString::number(value2)); . . . }
To read values sequentially, I am planning to implement a blocking structure by using waitForReceivedData(int timeoutInMs) function. If the expected value is observed in determined timeout period, I can set a flag and proceed to next reading operation :
void Widget::update() { readValue1(); waitForReceivedData(100); ui->labelValue1->setText(QString::number(value1)); readValue2(); waitForReceivedData(100); ui->labelValue2->setText(QString::number(value2)); . . . }
The thing is, I can receive different values externally besides update() function(with a push button) and these values may interfere in readSocket() function. Therefore, I may read wrong values in update() function.
I need to receive data in order in readyRead() function so that I can read true values in both update() function or other external events. When I researched about this, I encountered topics such as threads, queue etc. Maybe I can use a kind of lock mechanism or queue by using command id in packet that I send & receive.
What is the proper way to handle this ? I am kind of new to Qt so I will be very appreciated if you could help me
Regards
@TokaraForest
In outline, this is not the way to approach things in an event-driven UI system such as Qt. You ought not be attempting to sequentially read data and act on it they way you show. Better is to allow data to arrive and act on what you get when you get it.Basically you don't want to use any
waitFor...()
functions. They end up blocking the UI. Rather thanreadSocket()
directly doing UI updates, it should just append what it receives into a buffer, and emit a signal whenever a full "instruction" is received completely, however that is defined. A slot on that signal can then "parse" the latest complete data and, say update a single item in the UI. And so on. No "waiting".Are you in charge of the server-side? The responses it sends should be "marked" so the client knows when the message is complete, e.g. perhaps is sends lines ending in
\n
? That is much better then trying to use timers to calculate when you must have received a full "packet". -
@TokaraForest
In outline, this is not the way to approach things in an event-driven UI system such as Qt. You ought not be attempting to sequentially read data and act on it they way you show. Better is to allow data to arrive and act on what you get when you get it.Basically you don't want to use any
waitFor...()
functions. They end up blocking the UI. Rather thanreadSocket()
directly doing UI updates, it should just append what it receives into a buffer, and emit a signal whenever a full "instruction" is received completely, however that is defined. A slot on that signal can then "parse" the latest complete data and, say update a single item in the UI. And so on. No "waiting".Are you in charge of the server-side? The responses it sends should be "marked" so the client knows when the message is complete, e.g. perhaps is sends lines ending in
\n
? That is much better then trying to use timers to calculate when you must have received a full "packet".@JonB Thank you for your suggestion. I have followed the steps you mentioned.
@JonB said in How to receive data in order from TCP server ?:
Are you in charge of the server-side? The responses it sends should be "marked" so the client knows when the message is complete, e.g. perhaps is sends lines ending in \n? That is much better then trying to use timers to calculate when you must have received a full "packet".
Yes, I'm in charge of server side. I decide if the message is complete or not according to data length that server side sends.
But I still need to send multiple read requests periodically. Let's say I have to read 10 different values every 1 second (period isn't critical right now, it can be 3 or 5 seconds). Should I call read request related functions sequentially like in update function I mentioned (without waitFor...() functions) ? Is there a better way to do that ?
-
@JonB Thank you for your suggestion. I have followed the steps you mentioned.
@JonB said in How to receive data in order from TCP server ?:
Are you in charge of the server-side? The responses it sends should be "marked" so the client knows when the message is complete, e.g. perhaps is sends lines ending in \n? That is much better then trying to use timers to calculate when you must have received a full "packet".
Yes, I'm in charge of server side. I decide if the message is complete or not according to data length that server side sends.
But I still need to send multiple read requests periodically. Let's say I have to read 10 different values every 1 second (period isn't critical right now, it can be 3 or 5 seconds). Should I call read request related functions sequentially like in update function I mentioned (without waitFor...() functions) ? Is there a better way to do that ?
@TokaraForest
In addition to @JonB comments, understand that TCP is always "in order" because it is a stream transport. data is possibly fragmented by the network but is received and assembled in its transmitted order. You don't see the latter parts of the stream until all previous chunks have been received and inserted in the buffer.It seem what you're really asking about is transaction ordering, and that's up to the application as to how you do it. Please make sure to well define a transaction for your protocol. Ambiguities in the "state machine" between client and server will bite you.
-