网络通信中最常用的协议就是http协议,Qt对http协议的调用进行了封装,使用非常方便.Qt中使用Http协议与服务端通信的请求主要分为GET和POST,GET是从指定的资源请求数据,而POST是向指定的资源提交要被处理的数据。
从Qt4.4开始,引入了QNetworkRequest、QNetworkReply 和 QNetworkAccessManager等类来进行HTTP、FTP的操作,替代之前的QFtp和QHttp。要使用这些类,先在pro文件中引入network模块:
QT += network
QNetworkAccessManager
网络访问API围绕一个QNetworkAccessManager对象构建。由于QNetworkAccessManager基于QObject,因此只能从它所属的线程中使用它。
创建QNetworkAccessManager对象后,应用程序就可以使用它通过网络发送请求。 该类提供了一组标准函数,它们接收请求和可选数据,每个函数都返回一个QNetworkReply对象。返回的对象用于获取响应相应请求而返回的任何数据。
QNetworkAccessManager具有异步API,当http请求完成后,会通过finished信号进行通知.
常用的函数、信号槽
- QStringList supportedSchemes() const; 查看支持的协议
- QNetworkReply *get(const QNetworkRequest &request); //请求获取,具有异步,当http请求完成后,会通过finished信号进行通知
- 信号 void finished(QNetworkReply *reply);
- QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data);
//构建一个manager对象
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
//manager具有异步API,当http请求完成后,会通过finished信号进行通知
connect(manager,&QNetworkAccessManager::finished,this,&MyClass::replyFinished);
//发送异步get请求
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
也可以把get设置成同步
//这里也可以用一个QEventLoop来等待请求完成,但是我更爱用槽函数
QNetworkReply *reply=manager->get(request);
QEventLoop eventLoop;
connect(reply, &QNetworkReply ::finished, &eventLoop, &QEventLoop::quit);
eventLoop.exec();
QByteArray reply_data=reply->readAll();
QNetworkRequest
要发起一个get/post请求,首先要构建一个QNetworkRequest对象作为参数,它包含一个URL和一些可用于修改请求的辅助信息
常用函数
void setUrl(const QUrl &url);
//构建请求对象
QNetworkRequest request;
request.setUrl(QUrl("http://httpbin.org/get"));
request.setRawHeader("Content-Type","application/json");
有时需要在url中携带参数,如果手动进行字符串拼接不是很方便。Qt5.0提供了 QUrlQuery类,可以很方便的拼接和解析url中的参数。参考:
QNetworkReply
调用manager的get、post等接口后会返回一个reply对象,在manager的finished信号种也会传递该reply对象。如果要同步处理就在get、post后用事件循环等finished信号,如果是异步处理直接关联finished信号到槽即可。
常用函数:
- NetworkError error() const; //获取出错信息
- QString errorString() const;
- QVariant attribute(QNetworkRequest::Attribute code) const; code为HttpStatusCodeAttribute,获取http的状态码
- QUrl url() const; 获取url
- QByteArray readAll(); //获取返回来的数据
//connect(manager,&QNetworkAccessManager::finished,this,&MyClass::replyFinished);
//槽函数
void MyClass::replyFinished(QNetworkReply *reply)
{
if(reply->error()!=QNetworkReply::NoError){
//处理中的错误信息
qDebug()<<"reply error:"<<reply->errorString();
}else{
//请求方式
qDebug()<<"operation:"<<reply->operation();
//状态码
qDebug()<<"status code:"<<reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug()<<"url:"<<reply->url();
//qDebug()<<"raw header:"<<reply->rawHeaderList();
//获取响应信息
const QByteArray reply_data=reply->readAll();
qDebug()<<"read all:"<<reply_data;
//解析json
QJsonParseError json_error;
QJsonDocument document=QJsonDocument::fromJson(reply_data, &json_error);
if(json_error.error==QJsonParseError::NoError){
if(document.isObject()){
const QJsonObject obj=document.object();
qDebug()<<obj;
if(obj.contains("args")){
QJsonValue value=obj.value("args");
qDebug()<<value;
//QJsonValue(object, QJsonObject({"ie":"utf-8"}))
}
}
}else{
qDebug()<<"json error:"<<json_error.errorString();
}
}
reply->deleteLater();
}