[Qt-interest] Persistent HTTP connections
Mandeep Sandhu
mandeepsandhu.chd at gmail.com
Thu Feb 18 11:50:26 CET 2010
On Thu, Feb 18, 2010 at 2:56 PM, Mandeep Sandhu
<mandeepsandhu.chd at gmail.com> wrote:
>>>
>> In theory, it should work like that. Have you tried checking with a network
>> sniffer? If it's not like that, we have a bug (or let's call it performance
>> regression) in Qt.
>
> Thats exactly what I'm trying now...using a sniffer.
I tried using a singleshot timer to start the next download on
receiving the "finished" signal (see attached source). I then used
"NetActViewer" (http://netactview.sourceforge.net/) to view the active
TCP connections to my box (where the webserver is running).
I see that each time a new download starts, the client TCP port number
is changing. This means that a new TCP connection is being made each
time.
I also sniffed one HTTP transaction off the wire...
tshark shows the following for the HTTP request:
...
...
Hypertext Transfer Protocol
GET /dl.txt HTTP/1.1\r\n
[Expert Info (Chat/Sequence): GET /dl.txt HTTP/1.1\r\n]
[Message: GET /dl.txt HTTP/1.1\r\n]
[Severity level: Chat]
[Group: Sequence]
Request Method: GET
Request URI: /dl.txt
Request Version: HTTP/1.1
User-Agent: QT 1.0\r\n
Connection: Keep-Alive\r\n
Accept-Encoding: gzip\r\n
Host: 192.168.2.2\r\n
\r\n
...
...
HTTP response from server:
...
...
Hypertext Transfer Protocol
HTTP/1.1 200 OK\r\n
[Expert Info (Chat/Sequence): HTTP/1.1 200 OK\r\n]
[Message: HTTP/1.1 200 OK\r\n]
[Severity level: Chat]
[Group: Sequence]
Request Version: HTTP/1.1
Response Code: 200
Server: nginx/0.7.62\r\n
Date: Thu, 18 Feb 2010 10:01:21 GMT\r\n
Content-Type: text/plain\r\n
Content-Length: 6\r\n
[Content length: 6]
Last-Modified: Thu, 18 Feb 2010 08:56:44 GMT\r\n
Connection: keep-alive\r\n
Accept-Ranges: bytes\r\n
\r\n
...
...
So I guess it is using the correct header...but somehow a new
connection is being made each time.
-mandeep
>>
>> To be very sure, I would suggest to not create and send the request from the
>> finished() slot but one event loop spin after that. You can achieve this by
>> using a single shot timer set to 0 msec and sending the request from the
>> timer's slot.
>>
> Thanks for this tip.
>
> Regards,
> -mandeep
>
>>
>> Markus
>>
>
-------------- next part --------------
#include <QDebug>
#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QProgressBar>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
class DwnLoader : public QWidget
{
Q_OBJECT
private:
QString *url;
QNetworkAccessManager *netMan;
QNetworkReply *myReply;
QProgressBar *pBar;
int bufSize;
bool stop;
int dlCount;
public:
DwnLoader(QWidget *parent = 0);
public slots:
void download();
void slotReadyRead();
void finito();
void pauseDownload();
void progress(qint64 bytesReceived, qint64 bytesTotal);
};
DwnLoader::DwnLoader(QWidget *parent) : QWidget(parent)
{
QPushButton *quit = new QPushButton("Quit");
QPushButton *dl = new QPushButton("Download");
QPushButton *pause = new QPushButton("Pause");
pBar = new QProgressBar();
netMan = new QNetworkAccessManager(this);
url = new QString("http://192.168.2.2/largefile.txt");
bufSize = 128 * 1024;
dlCount = 0;
stop = false;
quit->setFont(QFont("Times", 18, QFont::Bold));
dl->setFont(QFont("Times", 18, QFont::Bold));
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
connect(dl, SIGNAL(clicked()), this, SLOT(download()));
connect(pause, SIGNAL(clicked()), this, SLOT(pauseDownload()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(dl);
layout->addWidget(pause);
layout->addWidget(pBar);
layout->addWidget(quit);
QWidget *inset = new QWidget(this);
inset->setGeometry(40,40,150,200);
inset->setLayout(layout);
}
void DwnLoader::download()
{
qDebug() << "Starting download from - " << *url;
QNetworkRequest request;
request.setUrl(QUrl(*url));
request.setRawHeader("User-Agent", "QT 1.1");
myReply = netMan->get(request);
myReply->setReadBufferSize( bufSize );
connect(myReply, SIGNAL(finished()),
this, SLOT(finito()));
connect(myReply, SIGNAL(readyRead()),
this, SLOT(slotReadyRead()));
connect(myReply, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(progress(qint64, qint64)));
}
void DwnLoader::finito()
{
qDebug() << "Fineeto!";
qDebug() << "Firing 0 msec timer. Count " << dlCount;
if (dlCount < 5) {
dlCount++;
QTimer::singleShot(0, this, SLOT(download()));
}
myReply->deleteLater();
}
void DwnLoader::progress(qint64 bytesReceived, qint64 bytesTotal )
{
if (stop) {
return;
}
pBar->setMaximum(bytesTotal);
pBar->setValue(bytesReceived);
}
void DwnLoader::pauseDownload()
{
if (stop) {
qDebug() << "Unpausing ...";
} else {
qDebug() << "Pausing ...";
}
stop = !stop;
slotReadyRead();
}
void DwnLoader::slotReadyRead()
{
if (myReply->error() != QNetworkReply::NoError) {
qDebug() << "ERROR: Error rx'ing my reply";
return;
}
if (stop) {
qDebug() << "STOPPING read! bytes available" <<
myReply->bytesAvailable();
return;
}
if (myReply->bytesAvailable() < bufSize) {
return;
}
QByteArray bytes = myReply->read(bufSize);
//qDebug() << "Ready read size = " << bytes.size();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
DwnLoader dwnLoader;
dwnLoader.show();
return app.exec();
}
#include "main.moc"
More information about the Qt-interest-old
mailing list