PDA

View Full Version : bug in Qt socket



dognzhe
11th June 2009, 04:45
I have two apps. one receive data with TCP socket , another generate the input. they both run the timer of 30 millisecond. receiver has to process the data that comes in. Reading and processing are in same thread. after few second receiver start to show that cannot keep up with input.(it could be a bug, or it could be that extra process take time) After 10 mins the difference is huge. for example: Receiver get package 1000, but input is package 5000. I believe all the data accumulated in lower level real socket buffer. The funy thing is that when I stop the input, the receiver stop getting data as well. this is not desired behavior. it should keep reading the data in the socket. In fact, readyRead () is not emitting any more.

Is this a bug? or i use it wrong?

nish
11th June 2009, 05:16
give minimal exaple code

dognzhe
11th June 2009, 05:43
Now I slow the input at 500 milisocond. there still are the big differences after while. what the hell going on with this QTcpSocket!!!!!!!!!!!!!!!!!!!!

dognzhe
11th June 2009, 05:49
void ClientSocket::tcpReady(){

QDataStream stream( &socket );
if(dataSize==0){

if(socket.bytesAvailable() < (int)sizeof(quint16)){
return;
}
stream >> dataSize;
}

if(dataSize <= socket.bytesAvailable()){
quint16 type;
qint32 frame;
qint32 x;
qint32 y;
QTime sendTime;
quint16 numOfMsg;
quint16 dir;
qint32 tankId;
bool dead;

stream>> numOfMsg;


for(int i=0;i<numOfMsg;i++){
stream>> type;

switch (type){
case PLAYER:
stream >>frame >>tankId>>x >>y >>dead>>sendTime;
//if(!checkPrediction(frame,x,y,dead)){
cannonPrt->updateTank(frame,tankId,x,y,dead,sendTime);
//}
qWarning()<< "type "<< type<<"frame: "<<frame<<"x: "<< x<< "y: "<<y <<"time: " << sendTime.toString("m:s:z");
break;
case BULLET:
stream >>frame >>x >>y >>sendTime>>dir;
qWarning()<< "type "<< type<<"frame: "<<frame<<"x: "<< x<< "y: "<<y <<"time: " << sendTime.toString("m:s:z") <<"dir "<<dir;
break;
case INITIAL:

stream>>frame >>x>>y>>tankId>>sendTime;
cannonPrt->setFrame(frame);
cannonPrt->addTank(true,tankId,x,y);
mainTankId=tankId;
label->hide();
break;
case CHECK:
stream >>frame>>sendTime;
if(cannonPrt->getFrame()-frame>20 || cannonPrt->getFrame()-frame<-20){
cannonPrt->setFrame(frame);
}
break;

default:
break;
}

}//end for loop


dataSize=0;
}

}


this is input



void ClientThread::sendMessage(){
#ifdef _DEBUG
qWarning("sendMessage %d\n", QThread::currentThreadId());
#endif
numOfMsg++;
if(numOfMsg>CHECK_PERIOD){
sendCheckMessage();
numOfMsg=0;
}
QList<QByteArray> dataToSend= cannonPtr->getDataToSend();
if(!dataToSend.isEmpty()){
QByteArray data;
QDataStream out( &data, QIODevice::ReadWrite );
out.setVersion(QDataStream::Qt_4_4);
out << (quint16)0;//reserve for size
out << (quint16)dataToSend.count();
for(int i=0; i<dataToSend.count(); i++){

data.append(dataToSend[i]);
//out<<dataToSend[i];

}
out.device()->seek(0);
out<< (quint16)(data.size() - sizeof(quint16));
#ifdef _DEBUG
quint16 size;
quint16 num;
quint16 kind;
qint32 frame;
qint32 id;
qint32 x;
qint32 y;
bool dead;
QTime time;
out.device()->seek(0);
out>>size>>num>>kind>>frame>>id>>x>>y>>dead>>time;
qWarning()<<"size: "<<size<<"num: "<<num<<"frame: "<<frame;
#endif
socketPrt->write(data);
socketPrt->waitForBytesWritten();

dataToSend.clear();
}
}

dognzhe
11th June 2009, 05:53
now I even stop the data process, so the whole thread is sitting there doing nothing but to read the incoming data and I set incoming rate to 500 millisecond(very slow rate). after while I still can see input send package 100 and receiver get package 80.. this is unbelievable~~~

wysota
11th June 2009, 16:06
I'd say your code is invalid. Aren't you experiencing any missing data anywhere "in the middle" of the transmission? I would really avoid creating a new data stream each time the socket emits a readyRead() signal.

dognzhe
12th June 2009, 03:37
I would really avoid creating a new data stream each time the socket emits a readyRead() signal.

thanks for suggestion, but what is wrong with create the new data stream every time?

data are perfectly deleveried

baray98
12th June 2009, 08:36
I think your problem is that you assume that your message is delivered as you send it.

Due to network traffic ,sometimes it will decide to split your messages into sub packets then in this case your client's recieve method is screwed.

Hint:
In every readyRead signal I would check if my previous numMessage is satisfied. or Put an end of transmission trigger so your client can check it if you have the full message.

Some more thoughts:
I don't think your loop using operator << will wait for another packet to arrive.

To prove my point try sendin a small message like 3 bytes @ a time. and maybe your network will deliver the full message everytime.

my 2 cents,

baray98