QTcpServer not sending data to browser until disconnectFromHost
-
Hi,
I'm using QTcpServer to provide a (very) lightweight html interface to my Qt desktop app. Its pretty easy to set up but I have one problem.
After receiving a readyRead() signal my socket, handleRequest, is called. This builds the HMTL page to serve and does QTcpSocket::write. Unfortunately the client (firefox in this case) does not receive the page unless I call QTcpSocket::disconnectFromHost, or close my desktop app (destructing the server).
I tried QTcpSocket::flush but this has not effect. Here's some code:
@
#include <fstream>
#include <sstream>
#include <QtNetwork/QTcpSocket>#define PORT_MIN 10000
#define PORT_MAX 10010HelpServer::HelpServer(QObject* parent)
: QTcpServer(parent)
{
quint16 p(PORT_MIN);
while (!listen(QHostAddress::LocalHost, p) && p < PORT_MAX) {
std::cout << "HelpServer Failed to listen on port " << p << std::endl;
++p;
}
std::cout << "HelpServer Listening on port " << p << std::endl;
}void HelpServer::incomingConnection(int socketfd)
{
QTcpSocket* client = new QTcpSocket(this); // Server is parent so owns memory on heap
client->setSocketDescriptor(socketfd);connect(client, SIGNAL(readyRead()), this, SLOT(handleRequest()));
}
void HelpServer::handleRequest()
{
QTcpSocket* client = (QTcpSocket*)sender();
if (client->state() != QAbstractSocket::ConnectedState)
return;QByteArray data = client->readAll();
std::string dataString(data.constData());std::cout << "HelpServer::handleRequest" << std::endl;
std::cout << dataString << std::endl;std::stringstream body;
body << "<html><body><h1>Hello</body></html>";// Build response
std::string response = "HTTP/1.1 200 OK\r\n";
response.append("Content-Type: text/html\r\n");// Separate HTML header from body
response.append("\r\n");// Add body and terminate
response.append(body.str());
response.append("\r\n");qint64 bytes = client->write(response.c_str()); // NOTHING SENT BY THIS ALONE
client->flush(); // HAS NO EFFECT
// client->disconnectFromHost(); // WORKS but I dont want to disconnect. I want 2 way comms via javascript.
std::cout << "HelpServer::handleRequest wrote " << bytes << " bytes:" << std::endl;
std::cout << response << std::endl;
}@
-
What does
@
std::cout << "HelpServer::handleRequest wrote " << bytes << " bytes:" << std::endl;
std::cout << response << std::endl;
@return? as in, what is the value of "bytes". I do know that for you to be able to write successfully out of a QTcpSocket that you must return from the event loop (cant be in any time of infinite loop).
Also, do you have Wireshark? Try to see if the packets are actually being sent over your network or whoever your sending it too. I have also had some issues with QTcpSocket from time to time, and setting:
@
client->setSocketOption(QAbstractSocket::LowDelayOption, 1);
@ -
The html page I am loading actually has a css reference in its header, and in reality I do get two network requests.
The first for the html page sends back a response of 406 bytes (correct) and the second css request sends back a response of 1000 bytes.
So the fact is the browser IS getting the html page, in order to go on to request the css it needs. And when I close the app, the page appears with the correct css styling.
If I don't close the app or add the disconnectFromHost call, Firefox just says 'Transferring data from localhost..." for a while before timing out.
I tried the low delay option, no change.
-
Try and increase size of content sent (so it's like 10kb or more) to browser.
When size of received data is not too big, browser probably just waits for more html to come so it can be rendered all at once. Experiment with bigger size of content should result in rendering what was received. However, 'Transferring data from {domain}…' message will be there until connection is closed. Otherwise, browser expects for more data to be received.
Unless you are trying to implement persistent connections (aka Http KeepAlive) then you should close connection right after each object is served (css and html page). -
Just tried sending a big page, 20k:
HelpServer::handleRequest wrote 20512 bytes
No change!No page is displayed until I close my app, then boom, it appears. I even tried null-terminating my data passed to write but clutching at straws atm.
-
Nonetheless, is it a problem to close connection after serving page?
-
I thought I would have to keep alive to enable javascript to talk to server through XMLSockets.
-
I'm not familiar with XMLSockets. However, when doing long polling with JQuerry for example, you force script to wait for some longer time (30s or so) for replay. After that time or as soon as data is available (whatever comes first) you create another long lasting http connection. Important thing is that connection is closed and reopened. Example: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery
As I said I'm not familiar with XMLSockets, but maybe you should simply try it with your http server? Maybe it will play nicely with long lasting connection.