PDA

View Full Version : HTTP Pipelining in Qt?



Ashley
16th April 2015, 17:06
I'm trying to implement http pipelining in Qt but I can't seem to get it working and there are no examples I can find on the internet. Currently my code looks like:


slotDataReceived(QNetworkReply){

// ...process reply...

// Send more GET requests as needed
while (responsesPending < maxPipelinedGets) //maxPipelinedGets is set to 6
{
QUrl* pServerUrl = new QUrl();
pServerUrl->setHost(mAddress);
pServerUrl->setPort(mPort);
pServerUrl->setScheme("http");
QNetworkRequest networkRequest(*pServerUrl);
networkRequest.setAttribute(QNetworkRequest::HttpP ipeliningAllowedAttribute, true);
networkRequest.setRawHeader("Host",mAddress.toLocal8Bit() + ":" + QString::number(mPort).toLocal8Bit());
networkRequest.setRawHeader("Pragma", "no-cache");
if(messageID != "")
networkRequest.setRawHeader("MsgID", messageID.toLocal8Bit());

cout << "Sending HTTP GET request";
networkManager->get(QNetworkRequest(*pServerUrl));
++responsesPending;
delete pServerUrl;
}
}

I still get responses from the server - but every time i get a response, 8 requests are sent, then 7 immediately come back with network reply errors, whilst one sits there waiting for another response, which suggests to me there is no http pipelining functionality present.

If anyone could help direct me to a working solution that would be greatly appreciated! :)

wysota
16th April 2015, 22:19
Does the server support pipelining?

BTW. Create QUrl on stack and not on heap.

Ashley
17th April 2015, 09:46
Does the server support pipelining?

BTW. Create QUrl on stack and not on heap.

Yes the server supports pipelining, I have seen it working with straight C++, but I am trying to get it to work with Qt.

And thanks for pointing that out with QUrl - no idea why I was allocating memory on heap. :p

wysota
17th April 2015, 10:06
I think your test may be flawed. QNetworkAccessManager spawns multiple connections (up to 4 I think but this is probably configurable) to handle requests so sending 6 request may not trigger pipelining. Reading the docs for QNetworkRequest::HttpPipeliningAllowedAttribute makes me think that QNAM may use pipelining if it decides that it makes sense. You can test the presence of NetworkRequest::HttpPipeliningWasUsedAttribute in the reply to see if pipelining did occur or not.

Ashley
17th April 2015, 10:20
I think your test may be flawed. QNetworkAccessManager spawns multiple connections (up to 4 I think but this is probably configurable) to handle requests so sending 6 request may not trigger pipelining. Reading the docs for QNetworkRequest::HttpPipeliningAllowedAttribute makes me think that QNAM may use pipelining if it decides that it makes sense. You can test the presence of NetworkRequest::HttpPipeliningWasUsedAttribute in the reply to see if pipelining did occur or not.

I ran the following test:


if(pReply->attribute(QNetworkRequest::HttpPipeliningWasUsedAt tribute) == QNetworkRequest::HttpPipeliningWasUsedAttribute)
{
cout << "HTTP Pipelining used";
}

and no reply reaches the cout statement so I'm assuming pipelining is turned off somehow

yeye_olive
17th April 2015, 10:36
According to the docs, the attribute QNetworkRequest::HttpPipeliningWasUsedAttribute has an associated QVariant value wrapping a boolean (QMetaType::Bool). Shouldn't your test be

if (pReply->attribute(QNetworkRequest::HttpPipeliningWasUsedAt tribute).toBool()) {
// ...
}
? I have not traced all the overloaded operators and constructors, but I suspect that your current test compares pReply->attribute(QNetworkRequest::HttpPipeliningWasUsedAt tribute) (a QVariant wrapping a boolean value) with QVariant::QVariant(9) (a QVariant wrapping the integer 9), which is not what you mean.

Ashley
17th April 2015, 11:04
According to the docs, the attribute QNetworkRequest::HttpPipeliningWasUsedAttribute has an associated QVariant value wrapping a boolean (QMetaType::Bool). Shouldn't your test be

if (pReply->attribute(QNetworkRequest::HttpPipeliningWasUsedAt tribute).toBool()) {
// ...
}
? I have not traced all the overloaded operators and constructors, but I suspect that your current test compares pReply->attribute(QNetworkRequest::HttpPipeliningWasUsedAt tribute) (a QVariant wrapping a boolean value) with QVariant::QVariant(9) (a QVariant wrapping the integer 9), which is not what you mean.

Thanks for the suggestion. The cout statement still doesn't get reached when I use .toBool()

wysota
17th April 2015, 12:57
This proves exactly nothing. The other attribute only marks a request as eligble for pipelining, it doesn't actually force pipelining.