概述
众所周知,Qt的网络操作类是异步(非阻塞的),但是有些场景却需要同步(阻塞)的网络访问,同时还需要加入超时设置(超过设定的时间,不再等待网络返回)。
1、示例代码
#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 如何实现HTTP的同步访问所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复