众所周知,Qt的网络操作类是异步(非阻塞的),但是有些场景却需要同步(阻塞)的网络访问,同时还需要加入超时设置(超过设定的时间,不再等待网络返回)。
1、示例代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#include <QtCore/QCoreApplication> #include <QObject> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QUrlQuery> #include <QUrl> #include <QEventLoop> #include <QTextCodec> #include <QTimer> void httpGET(const QString& strUrl, QString& response, int& statusCode) { assert(!strUrl.isEmpty()); const QUrl url = QUrl::fromUserInput(strUrl); assert(url.isValid()); // QNetworkAccessManager* manager = new QNetworkAccessManager; QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); QScopedPointer<QNetworkReply> reply(manager->get(request)); //wait. QEventLoop eventLoop; QTimer::singleShot(5000, &eventLoop, [&]() { if (eventLoop.isRunning()) { eventLoop.quit(); } }); QObject::connect(reply.data(), &QNetworkReply::finished, &eventLoop, &QEventLoop::quit); eventLoop.exec(QEventLoop::ExcludeUserInputEvents); //status code statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); //response if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); response = QString::fromLocal8Bit(data); } else { response = reply->errorString().toUtf8(); } reply->deleteLater(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); int statusCode = 0; QString response; QString strUrl = "http://wthrcdn.etouch.cn/weather_mini?citykey=101010100"; httpGET(strUrl, response, statusCode); qDebug() << "statusCode=" << statusCode << "nresponse=" << response; return a.exec(); }
2、知识点
2.1、EventLoop的事件类型
Constant | Description |
---|---|
QEventLoop::AllEvents | All events. Note that DeferredDelete events are processed specially. See QObject::deleteLater() for more details. |
QEventLoop::ExcludeUserInputEvents | Do not process user input events, such as ButtonPress and KeyPress. Note that the events are not discarded; they will be delivered the next time processEvents() is called without the ExcludeUserInputEvents flag. |
QEventLoop::ExcludeSocketNotifiers | Do not process socket notifier events. Note that the events are not discarded; they will be delivered the next time processEvents() is called without the ExcludeSocketNotifiers flag. |
QEventLoop::WaitForMoreEvents | Wait for events if no pending events are available. |
关于对 QEventLoop::ExcludeUserInputEvents 的理解:
用户输入的事件并不会被丢弃,而是等到QEventLoop 退出后再响应。像类似按钮按下和键盘按下,依然响应多次,只是响应的时间推迟。
2.2、超时的处理
引起网络连接超时的原因很多,比如:
- 网络断开,经常显示无法连接
- 网络阻塞,导致你不能在程序默认等待时间内得到回复数据包
- 网络不稳定,网络无法完整传送服务器信息
- 设备不稳定,如网线松动、接口没插好等等 网络注册时系统繁忙,无法回应
- 网速过慢,使用 BT 多线程下载,在线收看视频等大量占用带宽的软件
- 其他等等等原因
我们可以通过定时器,来实现超时控制。在达到超时限制时,自动退出EventLoop的事件循环,以此来避免网络的无尽等待。
最后
以上就是自觉哈密瓜最近收集整理的关于QT 如何实现HTTP的同步访问的全部内容,更多相关QT内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复