Unsolved I have a problem of abnormal message when using qt socket
-
Hi, I'm using qtsocket to write a client-server project. I have a client to send message and a server to process those message. But when the processing time is long, the messages that the server receives become abnormal and I can't read normal data sometimes.
The phenomenon is that I get normal message and intermittently some abnormal message. The abnormal message does not affect the following message. When I reduce the processing time, all the message becomes normal. Here is some of my code:
Client
QByteData message; QDataStream out(&message, QIODevice::WriteOnly); out<< Some Data socket->write(message); socket->flush();
Server:
//These codes are in ReadData() function QDataStream in(socket); if( block_size==0 ){ if( socket->bytesAvailable() < (int)sizeof(quint16) ) return; in>>block0_size; } if( socket->bytesAvailable() < block_size ){ return; } in>> Read message Call processing function block_size = 0;
I guess the problem is that when processing function runs for a long time, there are a lot of messages coming and buffer isn't large enough. But I don't know how to verify this hypothesis and neither how to fix it.
-
Hi,
What is a normal and an abnormal message for you ?
-
In principle there are three places where the error can be:
- in the client code
- in the server code
- somewhere in between (O/S or Qt)
3 will be very unlikely. and buffer overrun even more, as Qt uses unlimited buffers by default.
So I'd run Wireshark to see if the data looks as expected "on the wire". that should give you an hint where to investigate further - client or server side.
Happy New Year!
-
@SGaist I use a self-defined protocol, which contains message length, message type and some data and they are normal message. The message type of abnormal message is right, but the message type become messy and so does data.
-
if( block_size==0 )
vsin>>block0_size;
I guess it's just a typo. 2 notes:
- since Qt 5.7 you don't need that block_size magic any more and you can just use
QDataStream::startTransaction
/QDataStream::commitTransaction
. See theClient::readFortune()
method of the fortune example - you need to show us what's going on in
out<< Some Data
andin>> Read message
(the former is my prime suspect)
- since Qt 5.7 you don't need that block_size magic any more and you can just use
-
@VRonin I'm sorry, it's a typo error. I use Qt 5.2.1 so I can't use QDataStream::startTransaction.
My message is the position and lidar data of a smart car and let me show the details.
Client:QByteArray message; QDataStream out(&message, QIODevice::WriteOnly); out<<(quint16)0; out<<message_type; // message_type means the type of this message, for this lidar data message it is a fixed number long long timestamp=lidarData->timestamp; out<<timestamp; //Timestamp of this message out<<self_num; //It's the car number int size = lidarData->datasize; // The size of lidar data array out<<size; out<<x<<y<<ori; for( int i=0; i<size; i++ ) out<<lidarData->data[i]; // lidar data out.device()->seek(0); out << (quint16)(message.size() - sizeof(quint16)); //The length of this message socket_host->write(message); socket_host->flush();
Server:
//Receive message QDataStream in(socket); if( block_size==0 ){ if( socket->bytesAvailable() < (int)sizeof(quint16) ) return; in>>block_size; } if( socket->bytesAvailable() < block_size ){ return; } //Allocate local data short data[361]; //This 361 equals lidarData->datasize, which is lidar data size long long timestamp; quint32 from_num; int size; float x, y, orien; quint32 message_type; //Read message in>>message_type; if( message_type==1 ){ //if message_type is lidar data message in>>timestamp>>from_num>>size>>x>>y>>orien; for( int i=0; i<size; i++ ){ in>>data[i]; } qDebug()<<"Receive message from "<<from_num<<" message type "<<message_type<<",timestamp "<<timestamp <<", message size is "<<block0_size<<", x "<<x<<", y "<<y<<", ori "<<orien <<" data size "<<size<<" bytesAvailable "<<socket0->bytesAvailable(); UpdateMap(x, y, orien, size, from_num, data); } else{ qDebug()<<"Message type not 1"; }
The problem is about UpdateMap() function. If the process time of that function is short, all the message can be safely received. But if the time is long, the message_type of some message changes, it is not 1 and it becomes a huge negative number. All the data following the message_type becomes huge messy number.
-
- Given the problem it would be nice if you can add a comment specifying the type of every variable
short
andlong long
are not size safe. useqint16
andqint64
instead.data[361]
andin>>data[i];
is, in general, unsafe you might go out of bounds- if you receive anything that is not
message_type==1
you keep in the buffer all the rest - Where are these slots called from? are you using multiple threads?