天天看点

Qt之处理QNetworkAccessManager网络连接超时简述超时原因Qt 中的网络连接超时如何处理超时封装类

在网络操作中,经常会由于各种原因引起网络连接超时,究竟何为网络连接超时?

网络连接超时:在程序默认的等待时间内没有得到服务器的响应

<a href="#%e7%ae%80%e8%bf%b0">简述</a>

<a href="#%e8%b6%85%e6%97%b6%e5%8e%9f%e5%9b%a0">超时原因</a>

<a href="#qt-%e4%b8%ad%e7%9a%84%e7%bd%91%e7%bb%9c%e8%bf%9e%e6%8e%a5%e8%b6%85%e6%97%b6">qt 中的网络连接超时</a>

<a href="#%e5%a6%82%e4%bd%95%e5%a4%84%e7%90%86%e8%b6%85%e6%97%b6">如何处理超时</a>

<a href="#%e5%b0%81%e8%a3%85%e7%b1%bb">封装类</a>

引起网络连接超时的原因很多,下面,列举一些常见的原因:

网络断开,不过经常显示无法连接

网络阻塞,导致你不能在程序默认等待时间内得到回复数据包

网络不稳定,网络无法完整传送服务器信息

系统问题,系统资源过低,无法为程序提供足够的资源处理服务器信息

设备不稳定,如网线松动、接口没插好等等

网络注册时系统繁忙,无法回应

网速过慢,如 使用 bt 多线程下载,在线收看视频等大量占用带宽的软件 ,若使用共享带宽还要防范他人恶意占用带宽

计算机感染了恶意软件,计算机病毒,计算机木马等

在 qt 中,关于 qnetworkaccessmanager、qnetworkrequest 和 qnetworkreply 的文档中,找到了有关超时相关的错误 qnetworkreply::networkerror。

常量 qnetworkreply::timeouterror:

the connection to the remote server timed out

瞬间欣喜若狂,既然有超时错误,必然有设置超时的接口吧!遗憾,遗憾,遗憾。。。重要的事情说 3 遍,翻遍了官方文档,能和超时扯上关系的就这么一个简单的常量说明(当然还有 qnetworkreply::proxytimeouterror)。

这种情况下,我们只能自己去处理超时了。

解决思路:

使用 qtimer 启动一个单次定时器,并设置超时时间。

在事件循环退出之后,判断定时器的状态,如果是激活状态,证明请求已经完成;否则,说明超时。

首先,定义一个 qtimer,设置超时时间为 30000 毫秒(30 秒)并设置为单次触发。然后,使用 qnetworkrequest 实现一个简单的网络请求,通过 qnetworkaccessmanager::get() 开始获取 qt 官网的 html 页面内容。因为请求过程是异步的,所以通过使用 qeventloop 启动一个事件循环让其同步处理,并将 qtimer 的 timeout() 信号以及 qnetworkreply 的 finished() 信号连接至其 quit() 槽函数,保证在定时器过期之后或者网络响应完成后事件循环得到退出,不至于一直处于阻塞状态。

如上所述,事件循环退出的两种情况:

qtimer 30 秒到期,超时

网络连接响应完成

所以,当 qtimer::isactive() 激活的情况下,证明响应完成,还尚未超时。这时需要先调用 qtimer::stop() 来停止定时器,再对响做进一步处理。否则,进行超时处理 - qnetworkreply::abort() 立即中止操作并关闭网络连接。

既然以后会经常用到,那么还是提供一个封装类 qreplytimeout 专门处理超时。

由于 qnetworkreply 和 qreplytimeout 是父子关系,所以 qreplytimeout 将被自动销毁。

使用起来非常简单:

如果对 google 的获取未在 1000 毫秒(1 秒)内完成,则会中止,并发出 timeout() 信号,供进一步处理(例如:提示用户请求超时)。

继续阅读