• Qt HTTP内部构架


    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线程中的操作提供了一个接口。所有在 QNetworkReplyHttpImpl 和 QHttpThreadDelegate 之间的跨线程通信和数据传递都是通过信号和槽完成的。这意味着Delegate提供了一些槽,由HttpImpl发出的信号所触发,反之亦然。

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

    该Delegate提供了用来组建HTTP请求和响应的类,名为 QHttpNetworkRequest和 QHttpNetworkReply 。这个名字会让人困惑,因为我们已经拥有了公开接口 QNetworkRequest 和 QNetworkReply ;这两个公开接口提供了大量HTTP特有属性的访问接口,例如设置HTTP流水线、状态码和其他HTTP头。而这两个内部类 QHttpNetworkRequest 和 QHttpNetworkRply 则用以解析从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的解析和发送,请参见 QNetworkCookie 和 QNetworkCookieJar 。
    • HTTP缓存 :尽管Qt也支持HTTP缓存,但未被默认启用。
    • 代理服务器 :Qt支持在HTTP和SOCKS5代理服务器上进行网络传输。
    • 上传数据 :一些关于上传数据,以及处理HTTP multipart消息的类被省略了。

    http://www.tuicool.com/articles/U7BBrm

  • 相关阅读:
    .emacs
    boost 程序库完全开发指南_ch3_memory_manager
    C++ 友元函数
    AutoHotKey.ini
    QQ因系统日期无法打开
    SharePoint 2007中如何更改用戶基本資料(EMail地址)
    盗版Windows XP如何安装IE7
    三人行,必有我師學會了家中布線ADSL上網
    以數據源方式讀取文本文件連接串及注事事項
    网络访问时you might not have permission to use this network resource错误解决方法
  • 原文地址:https://www.cnblogs.com/findumars/p/6090334.html
Copyright © 2020-2023  润新知