Back to Blog home

Qt HTTP内部构架

Published on 星期四 三月 08, 2012 by Xizhi Zhu in Qt HTTP qtearth-blogs-chinese | Comments

原文链接 Peter Hartmann - Inside the Qt HTTP stack

Qt HTTP组件是Qt中所有HTTP通信的基础,例如被用于Qt Webkit中。在Qt 5中,HTTP实现中有相当部分被重写,其中大部分的工作是woboq的Markus完成的。这篇文章将试图分析HTTP组件的内部结构,注意出于简化的目的,一些类被省略。

我们可以用如下的方法使用公开接口。

简单的例子

QUrl url("http://qt.gitorious.org");
QNetworkRequest request(url);
QNetworkAccessManager manager;
QNetworkReply *reply = manager.get(request);
QObject::connect(reply, SIGNAL(finished()), myClass, SLOT(replyFinished()));

1. 公开接口及其朋友

以上的例子展示了主要的接口:使用QUrl来创建被用来表示一个HTTP请求的QNetworkRequest。该请求被传递给QNetworkAccessManager,该类负责在网络上发送请求,并返回一个表示HTTP响应的QNetworkReply。根据URL所采用协议的不同,QNetworkAccessManager会创建QNetworkReply的不同内部子类;如果URL采用了“http://”或者“https://”协议,则会创建一个QNetworkReplyHttpImpl实例。该类是用来设置请求,并在发送请求前向其添加例如缓冲或者cookie等信息。

如果该请求被用作上传数据(例如使用HTTP POST或者PUT),该实现类会用到QNonContiguousByteDevice。这个非连续字节类能够用来在不执行memcpy操作的环境中读取文件、字节等。

这些接口可用如下的UML图表示:

2. 工作线程

在Qt 4.8中引入一个特性是多线程的HTTP后端:这个新的后端在一个单独的线程中收发数据,并进行HTTP消息解析(更多细节请参见这篇文章)。

QNetworkReplyHttpImpl会创建一个名为QHttpThreadDelegate的类,并将其放置在这个新的线程中(被称为HTTP线程)。这个QHttpThreadDelegate是一个Facade类,为所有在HTTP线程中的操作提供了一个接口。所有在QNetworkReplyHttpImplQHttpThreadDelegate之间的跨线程通信和数据传递都是通过信号和槽完成的。这意味着Delegate提供了一些槽,由HttpImpl发出的信号所触发,反之亦然。

每当QNetworkReplyHttpImpl被创建时,它都会创建一个相应的QHttpThreadDelegate,链接相应的信号和槽,并将该Delegate移动到HTTP线程中去。

该Delegate提供了用来组建HTTP请求和响应的类,名为QHttpNetworkRequestQHttpNetworkReply。这个名字会让人困惑,因为我们已经拥有了公开接口QNetworkRequestQNetworkReply;这两个公开接口提供了大量HTTP特有属性的访问接口,例如设置HTTP流水线、状态码和其他HTTP头。而这两个内部类QHttpNetworkRequestQHttpNetworkRply则用以解析从socket数据流中接受到的HTTP消息,以填充HTTP头和实体。

下图展示了将这几个类添加到类图后的结构。

3. 更底层

HTTP请求和相应是在所谓的“频道”上进行收发的;简单的说,每个“频道”就是一个socket,并附加了一些用于维护HTTP状态和特性的逻辑。对于普通的HTTP请求,通常采用QTcpSocket作为该频道上的socket,而对于“https://”则采用QSslSocket

一系列连接到同一服务器的频道组成一个连接。对于和同一个服务器的通信,这里总是只有一个连接,以及最多同时有六个频道。此外,当HTTP流水线被启用的时候,还可以同时发出更多的请求。当通过socket接收到一个相应时,该socket并不会被自动关闭,而是默认被用作后续请求,从而节省socket的初始化时间并重用一个已经具有更大TCP窗口值的socket。

现在,HTTP内部结构的UML图已经基本完整了:

4. 其他

到目前还有两个重要的类未被提及:

  • QNetworkSession:该类主要用于移动设备之中,特别是在缺少互联网的持续连接的环境中。当缺乏对互联网的连接时,QNetworkSession及其相关类会尝试创建一个连接(例如,程序可以连接QNetworkSession的信号,让用户在3G和Wifi连接之间进行选择)。该类被QNetworkAccessManager初始化。
  • QNetworkAccessAuthenticationManager:该全局类被用于存储能够被重用的认证信息。当服务器要求认证时,QNetworkAccessManager会发出一个信号(QNetworkAccessManager::authenticationRequired()),要求用户输入用户名和密码。而这个认证管理器类则会缓存此信息,并在后续的请求中自动将其发送给服务器。有趣的是,这个认证管理器也使用了QNetworkAccessCache,和QHttpNetworkConnection用来缓存连接一样。

因此,(本文中提及的)Qt HTTP内部构架的完整类图如下所示:

还有哪些未被提及

尽管上面这个类图已经显得够复杂了,但还有一些类和领域被省略了:

  • Bearer类:用于更加细粒度的调节连接设置等,除了前面提到的QNetworkSession外还有几个类被用到。
  • Cookies:显然,Qt HTTP默认支持cookie的解析和发送,请参见QNetworkCookieQNetworkCookieJar
  • HTTP缓存:尽管Qt也支持HTTP缓存,但未被默认启用。
  • 代理服务器:Qt支持在HTTP和SOCKS5代理服务器上进行网络传输。
  • 上传数据:一些关于上传数据,以及处理HTTP multipart消息的类被省略了。

Subscribe to Our Blog

Stay up to date with the latest marketing, sales and service tips and news.

?
zeecrowddev
0 points
125 months ago

AHOU !!!!!

?
Daniel Lohse
0 points
125 months ago

Unfortunately, trying to install the Qt Enterprise Evaluation on OS X Yosemite.

»Could not download archive: https://cdn.qt.digia.com/qt... Error downloading
https://ordp.qt.digia.com/q... - server replied: Not Found«

Have tried this morning (11am UTC) as well as just now (2pm UTC) without any luck. Offline packages are not available yet for Qt 5.4 and OS X.

Any pointers?

?
Tuukka Turunen
0 points
125 months ago

@Daniel Lohse: There is a problem with Mac online installer. We are currently working to fix this. Sorry for inconvenience. Due to sync times needed to get this fixed, best if you can try this again tomorrow.

?
Daniel Lohse
0 points
125 months ago

Alright, thanks for the fast reply! :)

?
Michael Lykke
0 points
125 months ago

Great. Is the source version QtCharts 2.0 for enterprise users going to be available for us that builds from source?

?
Jani Heikkinen
0 points
125 months ago

src packages for enterprise add-on components will be available with final release

?
HGH
0 points
125 months ago

"Qt 5.4 RC packages also contains Qt Creator 3.3 RC and in commercial packages candidates for new commercial value-add items as well."

Sadly the online installer doesn't.

?
Jani Heikkinen
0 points
125 months ago

Yeah, unfortunately we cannot add Qt Creator RC packages available via online installer at the moment. It will be available via online installer when final version is released

?
HGH
0 points
125 months ago

What is the meaning of these warnings when starting a new project in Qt Creator. Do they denote a problem or is it normal:
Warnings while parsing QML type information of D:/SDKs/Qt/5.4/mingw49132/imports/QtWebKit:
Failed to parse "D:/SDKs/Qt/5.4/mingw491
32/imports/QtWebKit/plugins.qmltypes".
Error: 1:1: Expected token numeric literal' Warnings while parsing QML type information of D:/SDKs/Qt/5.4/msvc2013_64/imports/QtWebKit: Failed to parse "D:/SDKs/Qt/5.4/msvc2013_64/imports/QtWebKit/plugins.qmltypes". Error: 1:1: Expected tokennumeric literal'

?
NuShrike
0 points
125 months ago

Building from git (a few days ago), Qt 5.4.x android-x86 seems entirely broken.

Specifically in the construction of QQmlEngine. Has this been tested?

?
NuShrike
0 points
125 months ago

Still SIGSEGV in runnig an android-x86 QML app.

Very easy to replicate by creating a new stock QML app in QtCreator and try deploying onto Android-x86 device. Immediate SIGSEGV in void QV8Engine::initializeGlobal(): line 537 when constructing the QV4::Scoped result(...) using FREEZE_SOURCE.

I suspect the recent vararg changes is causing this segfault for x86 Android. No issues on ARM.

?
Eskil Abrahamsen Blomfeldt
0 points
125 months ago

Hi,

Could you please report bug findings in http://bugreports.qt-projec...

Thanks! :)

?
Robin Lobel
0 points
125 months ago

Is there a reason you keep VS2013 OpenGL-only builds (since dynamic OpenGL builds are also available for VS2013) ?

?
Jani Heikkinen
0 points
125 months ago

It was agreed to start using -opengl dynamic by replacing old -angle configurations with it. If all goes OK I don't see any reason to continue keeping those separate opengl installers in 5.5 anymore

?
Kari T
0 points
125 months ago

What about GStreamer 1.0 support in QtMultimedia? GStreamer 0.10 has been abandoned since 2013!

?
chris
0 points
125 months ago

thanks a lot for your work
still no plans for mingw64 binaries?

?
Jani Heikkinen
0 points
125 months ago

Hi,
No plans to deliver minGW64 binaries at the moment. As I wrote earlier we cannot increase amount of binary installers anymore and so on 32bit version is good compromise.

?
Malek Khlif
0 points
125 months ago

Veryyyyyyyyyyyyyyyyyyyyyyyyyyyyy Gooooooood :)))

?
shudingbo
0 points
125 months ago

windows x86 opengl not QWebEngine module? Why? forget?

?
Stefan Fröberg
0 points
125 months ago

What is the lowest x86 machine that can run apps compiled against this? Pentium 3 ?

?
mike
0 points
125 months ago

Is QtCanvas3D planned to be released alongside Qt 5.4?

?
Tuukka Turunen
0 points
125 months ago

@mike: Yes, as a technology preview.

?
lasconic
0 points
125 months ago

The accessible widgets and quick plugins are missing on Windows mingw. I hope it's a bug https://bugreports.qt-proje...

?
Ed Sutton
0 points
125 months ago

Qt5.4 RC Android builds now display QTableWidget headers and QGraphicsView as all black. I had never seen this problem under Qt 5.4 Beta.

I was hoping to find a Qt example that replicates the problem but unfortunately the Qt 5.4 RC item view examples do not build on Android. Many errors on invalid character. I tried coloreditorfactory, frozencolumn, and editable tree model examples.

Fortunately I have not emptied my trash of Qt5.4 beta yet.

-Ed

?
J-P Nurmi
0 points
125 months ago

Hi Ed, this was an unfortunate regression caused by the fix to https://bugreports.qt-proje.... The good news is that the regression has been already fixed (https://codereview.qt-proje...) and should be available in the final 5.4.0 release.

?
roi
0 points
125 months ago

Do you still plan to release Qt3D?

?
mblgrano
0 points
125 months ago

wht MinGW 4.9.1 included is not last version
who is 4.9.2?

?
Tom Rezek
0 points
125 months ago

Qt5.4 RC fails to compile my project that compiled under Qt5.3.2 because it has more than one qrc file in the project.

When there are more than one qrc files in a project, qtquickcompiler fails on manglenamespace due to redefinition of "qInitResourcesC".

Here is the result when you alter the Qt example "rssnews" to pull the qml files from a second qrc file, in this case named rrrnews2:

int QTMANGLENAMESPACE(qInitResourcesC)() {
QtQuickCompilerGeneratedModule::registerCompilationUnits();
QINITRESOURCE(rssnewsqtquickcompiler);
return 1;
}
int QT
MANGLENAMESPACE(qInitResourcesC)() {
QtQuickCompilerGeneratedModule::registerCompilationUnits();
QINITRESOURCE(rssnews2);
return 1;
}_

?
Tom Rezek
0 points
125 months ago

I can reproduce the qtquickcompiler bug in the 5.4rc1 example "customparticle" simple by checking "Enable Qt Quick Compiler" in the qmake build steps.

?
Adrian Gabureanu
0 points
125 months ago

1) Is sound supposed to work now on Windows Phone or WinRT? I, for one, haven't been successful in playing sounds, regardless of their source or the QML type used.

2) Will there be any tutorials on how to mix C# and Qt C++ ? Or at least some sample apps on GitHub?

3) I've noticed a new add-on: Qt Quick 2D Renderer. Any documentation on how to use it and trigger its functionality?

?
MS1000
0 points
125 months ago

Does this version of Qt let users use the translucent surfaces from OS X Yosemite? This is something I would really like to be able to use for a Python program

?
Hasan
0 points
125 months ago

Does At 5.4 support OSX/iOS app extension? Like today, Share, etc.

Thanks.

?
Hasan
0 points
125 months ago

Sorry, I will mean Qt 5.4