Server not reading all data
-
ok here is my basic problem. I have a simple server that reads in a file from a client. The issue i have is the fact that it does not always read in the data in full. I am not sure if it is a client or server issue. I have tested the amount of bytes in the socket as it writes and it is the correct size. But on the other end it sometimes receives them all, or it only recieves some. So I am guessing that the issue exists somewhere in my server code. Here is the server slot:
@void Server::clientconnected()
{//cout<<"Hello"; QTcpSocket *client = new QTcpSocket; client = server->nextPendingConnection(); client->waitForReadyRead(-1); QByteArray clientIn = client->readAll(); QString input(clientIn); client->flush(); if(input == "UPLOAD") { cout<< "Welcome"; client->waitForReadyRead(-1); QByteArray in = client->readAll(); client->flush(); client->errorString(); qDebug() << in.size(); QString run(in); QVariant x = run; // qDebug() << run; if(!client->waitForBytesWritten(-1)) { client->errorString(); } //client->flush();
// QSqlQuery query;
// query.exec("INSERT INTO SocketTest(Title,Description) VALUES('xml','"+in.toHex()+"')");
// //client->waitForReadyRead(10000);
//client->disconnectFromHost();//db.close(); if(client->bytesAvailable() == false) { client->deleteLater(); client->disconnectFromHost();
}
}
else
if(input == "DOWNLOAD")
{cout<<"Hello"; } connect(client,SIGNAL(disconnected()), client, SLOT(deleteLater()));
}
@
can anyone see something that i dont?
oh here is the client side too, just in case i missed something
@
sock->write("UPLOAD");
sock->flush();
sock->waitForBytesWritten(100);// sock.waitForReadyRead(1000);
// QByteArray Bytes = sock.read(100);
// QString msgs(Bytes);
// cout << msgs.toStdString() << endl;
// sock.flush();QFile file("C:/Users/admin/Desktop/SocketConnection/Files/test.xml");
if(!(file.open(QIODevice::ReadOnly)))
{cout<< "Files Could not be opened";
}
else
cout<< " file opend successfully" <<endl;QByteArray blah; QTextStream out(&blah,QIODevice::WriteOnly); out << (quint32)0; out << blah; sock->flush(); blah = file.readAll(); file.flush(); QString eh(blah);
sock->waitForReadyRead(1000);
sock->write(blah); qDebug() << sock->bytesToWrite(); qDebug() << sock->bytesAvailable(); qDebug()<< sock->atEnd(); sock->waitForBytesWritten(); if(sock->atEnd() == true) { qDebug()<< "still data to write"; sock->flush(); sock->disconnectFromHost(); } //qDebug()<< sock->bytesAvailable(); //sock->flush(); qDebug() << blah.size(); return a.exec();
}
@ -
First: Please do yourself and your readers a favor and format the code nicely. Multiple empty lines, unaligned indenting, commented code that is totally unrelated etc. makes the code hard to read and might people make ignore your post at all. If you want their time to be invested on your code, invest your time to make their live easy.
Regarding your code:
You have a memory leak in lines 9 and 12. The object on the heap, created in line 9 with new, will never be destroyed because you immediately overwrite the pointer in line 12.
Regarding the problem you stated:
Your first readAll in line 15
@
QByteArray clientIn = client->readAll();
@might read more than only "UPLOAD", it is very likely that actual file data has already arrived. Your QString input then contains "UPLOAD" + some more bytes and your comparison in line 23 fails. It will neither match "DOWNLOAD" on line 67 so your if-else statement will fail completely.
Insert this in line 19 to see the actual contents of input:
@
qDebug() << input
@Some closing advice:
It's easy to mine the code with debug output or use the debugger, set some breakpoint and look what's actually in your variables. This way you would have seen all this yourself. -
Thanks for the info on the memory leak. I figured out what was going on though and now im getting all of my data. I tested whether or not input and download were actually working and they are. I do see how that would happen though and i plan on fixing it. Thanks
-
I'd suggest you append a newline after your indicator string ("UPLOAD", "DOWNLOAD"). With that you can use "QIODevice::readLine() ":http://doc.qt.nokia.com/stable/qiodevice.html#readLine-2 (which is inherited by QTcpSocket) to get the mode, the rest of the uploaded bytes remain in the socket's buffer to be read later on.
-
Could i not just limit the amount of bytes transfered to say 10, and only read 10 on the server side. The message sent by the client is always going to remain the same. That way i know im not going to get any extra bytes.
-
You can do whatever you want if you do it the right way and consider all corner cases, keep your unused data and so forth. If you're clever you design your protocol with "KISS":http://en.wikipedia.org/wiki/KISS_principle in mind. Your 10 bytes solutions seems not to fit into that, though :-)
-
Thanks for the help