Incomplete Data When reading Threaded TCP Socket
-
I have an http server
@server = new httpserver(this);
connect(server,SIGNAL(newConnection()),this,SLOT(newconnection()));@reimplemented incomingConnection so that I can create the socket and read it in a new thread.
@void httpserver::incomingConnection( int socketDescriptor ) {
DESCRIPTOR = socketDescriptor;
}@then in newconnection slot:
@void serverapp::newconnection() {
processor *process = new processor(server->DESCRIPTOR, this); connect(process, SIGNAL(finished()), process, SLOT(deleteLater())); process->start();
}@
inside run:
@void processor::run() {
QTcpSocket *socket = new QTcpSocket(); socket->setSocketDescriptor(DESCRIPTOR); socket->waitForReadyRead(); QByteArray text = socket->readAll(); ...
}
@When I recieve a POST request it sometimes reads all the data, other times not. It only reads the header info and not the actual content:
POST /admin HTTP/1.0
Host: abc.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-ZA,en-GB;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://abc.com/admin
Content-Type: application/x-www-form-urlencoded
Content-Length: 64
Connection: keep-aliveNO URL-ENCODED STRING HERE!
But, when I don't thread it or reimplement tcpserver I get all the data with url-encoded content every time.
@QTcpSocket *socket = server->nextPendingConnection();
socket->waitForReadyRead();
QByteArray text = socket->readAll();
print(QString::fromLocal8Bit(text.data(), text.size()));@ -
I think I have a solution:
@while( socket->waitForReadyRead() ){}@
When you just call waitForReadyRead it stops waiting as soon as some data is ready for reading and not all. So, bytesAvailable will be inaccurate as well. By keeping it in the loop you're waiting for all the data to become ready before it turns false.
It kinda takes a bit longer while sitting in the loop almost like it is not going to exit the loop, but it eventually does and I can read all the data. Doesn't seem like the best solution though. It obviously waits I guess to timeout (default 30sec) and I can't quit before that because I don't know the right amount of data I'm waiting for.
-
Hi! I think better use readyRead() signal instead while().
-
Thanks for responding. I tried that and numerous other approaches before I came here. Readyread is emitted when waitForReadyRead is called. And you get the same result. It doesn't wait for all the data. I figured out the best solution for my situation though. Using socket->peek in a loop instead. I read the header and check Content-Length. Then calculate how much data I still need to wait for before I exit the loop. My problem is solved, but if anyone has a way to check how much data is expected, maybe by reading the bytearray header or something it might help others who get incomplete data because they can't determine how much data they are supposed to recieve.