2020年10月5日(星期一)M rten Nordheim,Timur Pocheptsov | 评论意见
在这篇博文中,我们想告诉你一些最近的更新和变化QT网络接收到的模块QT 6,以及一些潜在的未来发展。.
QNetworkAccessBackend是一个抽象基类,用于与缓存、文件和ftp后端进行接口。我们在Qt中使用QNetworkAccessBackend已经有一段时间了,但是不可能以任何合理的方式使用QtNetwork外部。现在是了!在Qt 6中,我们计划将ftp后端移出QtNetwork,并将其单独作为插件分发。为此,我们使QNetworkAccessBackend更易于从外部使用,并使QNetworkAccessManager能够在运行时加载这些插件。与我们的一些其他插件接口一样,它没有Qt本身所具有的严格的向后兼容性承诺,它需要链接到QtNetworkPrivate才能使用它。
我们希望能够专门研究各种后端的一些行为。例如,非网络后端不需要我们为目标URL准备代理列表。为此,我们添加了三个不同的枚举,每个枚举中有几个值:
其中,只需要“TargetType”,目前只指定后端支持的目标是否联网和/或本地。
由于这种方法,如果没有启用某些功能,某些函数可能不会执行任何操作。其中一个例子是IO特性‘ZeroCopy’,它启用了readPoter()和AdvanceReadPoter()函数。如果没有启用,这两个函数将不会被调用。拥有这个功能系统的主要思想是,我们可以在不破坏任何现有代码的情况下进行这些改进。新代码必须选择加入新特性。不过,要重申的是:我们不能保证网络访问后端插件与使用Qt生成的应用程序具有相同的向后兼容性。
要实现网络访问后端插件,您需要实现从QNetworkAccessBackendFactory继承的类。如果支持所请求的方案,该类将完成创建后端的工作。您还需要创建一个从QNetworkAccessBackend继承的类,如果您的类支持“ZeroCopy”功能,则需要覆盖所有纯虚拟函数,以及“read()”或“readPoter()”和“AdvanceReadPoter()”。至于现有的用途,QNetworkAccessCacheBackend和QNetworkAccessFileBackend都会被更新以使用新的接口,尽管它们是直接编译到Qt中的,而不是目前作为插件分发的。
在Qt 6中,我们放弃了SPDY支持。SPDY是一个开放规范的实验协议,它主要是在Google开发的。SPDY成为HTTP/2协议的前身和原型;HTTP/2的引入淘汰了SPDY,今天SPDY已被废弃。
在保持与HTTP/1.1(例如与方法、状态代码、URI和大多数头字段)的兼容性的同时,HTTP/2还添加了:
在Qt 6之前,必须通过设置以下属性之一手动启用HTTP/2协议:
例如:
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, true);
对于“Http2异体Attribute”,QNetworkAccessManager将应用层协议协商用于“https”方案,协议升级报头“h2c”用于“http”方案。如果您事先知道服务器在所谓的“直接”模式下支持HTTP/2,而不需要协议协商,那么第二个属性是有用的。
在Qt 6中,默认情况下启用了HTTP/2支持:这意味着属性‘Http2合金化Attribute’设置为‘true’。如果无法协商HTTP/2,则QNetworkAccessManager将回到HTTP/1.1。如果您的应用程序只能使用HTTP/1.1,则可以为新的网络请求将属性‘Http2合金化Attribute’设置为‘false’:
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
这个“默认启用”规则有一个例外:
QNetworkAccessManager::connectToHostEncrypted(host, port, configuration);
使用此函数,应用程序可以预连接到服务器,而无需发送任何请求。如果我们要在这样的连接上启用HTTP/2,对于希望使用HTTP/1.1并通过使用请求属性禁用HTTP/2的应用程序来说,这种连接将是无用的。可以通过在“配置”参数中设置所需的协议列表来显式启用http/2,例如:
auto tlsConfig = QSslConfiguration::defaultConfiguration();
tlsConfig.setAllowedNextProtocols({QSslConfiguration::ALPNProtocolHTTP2});
manager.connectToHostEncrypted(host, port, tlsConfig);
另一个可能影响您的网络代码的更改是QNetworkAccessManager在Qt 6中使用的默认重定向策略。策略API最初是在Qt 5中引入的,考虑到在Qt 6中切换到默认的自动重定向处理的想法。
QNetworkAccessManager支持由枚举QNetworkRequest::RedirectPolicy描述的几个重定向策略。这些政策是:
从Qt 6开始,QNetworkAccessManager在发出请求时将使用的默认重定向策略是QNetworkRequest::NoLessSafeRedirectPolicy(禁止从‘https’重定向到‘http’的策略)。
如果您的应用程序依赖于连接到QNetworkReply::redirected()的插槽来处理重定向,则必须将策略设置为QNetworkRequest::ManualRedirectPolicy和Qt 6:
req.setAttribute(RedirectPolicyAttribute, ManualRedirectPolicy);
承载管理是为支持漫游和管理某些设备上的连接而历来需要的机器的名称。它还可以选择在连接互联网时使用的设备网络接口中的哪一个。今天,情况已不再如此,因为操作系统通常自行处理漫游,并将自动选择最佳的网络接口发送数据,通常不会为应用程序提供任何影响这些选择的方法(或不方便的方式)。.
尽管QNetworkManager提供了API来选择要使用的接口或配置正在使用的接口,但这一新的现实意味着,当前支持的平台没有为Qt提供一种可靠的方式来满足请求。同时,跟踪网络状态的尝试引发了各种问题,如Windows上的wifi流量过多,导致了很高的ping次数,或者在短暂的网络中断之后,Qt无法识别网络已经恢复,导致所有后续请求失败。
考虑到新的现实也使得承载管理在很大程度上是多余的,我们决定是时候退休Qt网络的这一部分了。
仍然有用的一个特性是能够检查连接性并获得连接更改的通知。到目前为止,QT6.0中还没有出现替换,尽管我们已经收集了一些用例,并希望在即将发布的小版本中对该功能进行替换。如果您有特定的用例,您希望看到涵盖的情况,或者您希望跟踪此任务的进度,那么请转到QTBUG-86966.
在Qt 6中,QSslSocket接收了额外的API,提供了有关作为TLS协议一部分接收或发送的警报消息的信息。我们有两个新的枚举:
QSslSocket中有两个新信号:
如果可能,这些信号还会报告问题的文本描述(如果由TLS库提供)。
与TLS握手相关的另一个更改是,在握手仍在进行中时,能够报告在握手过程中遇到的错误。这些错误直接从验证回调中报告。QSslConfiguration有一个新的getter和setter:
QSslSocket有一个新的信号:
并且必须忽略一个函数来表示错误:
如果未忽略错误,则基础TLS库将向对等方发送警报消息。
对于使用QNetworkAccessManager的应用程序来说,这个API有点低,不太感兴趣。但是,如果您直接使用QSslSocket,在调试目的或实现某些错误或警告处理逻辑时,它会非常方便。这个改变目前正在使用我们的OpenSSL后端;我们使用的其他TLS库没有必需的API,或者没有提供我们需要的完整信息。
嗯,这部分并不完全是关于Qt 6已经有什么。也是关于未来可能的发展。到目前为止,Qt 6支持TLS协议的最新版本,即1.3,这要归功于我们的OpenSSL后端(Qt 5也支持TLS 1.3)。我们正致力于在SChannel后端启用TLS 1.3。不幸的是,没有可用的TLS库作为替代,只在BoringSSL的基础上构建了一些更高级别的框架(请注意这一点的讽刺性!)这意味着,对于我们的达尔文用户,我们将在未来提供一个替代方案。对于QNetworkAccessManager来说,在像NSUrlSession这样的Apple类之上实现一个新的QNetworkAccessBackend非常方便(其中包括TLS 1.3和实验性HTTP/3支持!)