网络通信中最常用的协议就是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信号进行通知.

常用的函数、信号槽

  1. QStringList supportedSchemes() const; 查看支持的协议
  2. QNetworkReply *get(const QNetworkRequest &request); //请求获取,具有异步,当http请求完成后,会通过finished信号进行通知
  3. 信号 void finished(QNetworkReply *reply);
  4. 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信号到槽即可。

常用函数:

  1. NetworkError error() const; //获取出错信息
  2. QString errorString() const;
  3. QVariant attribute(QNetworkRequest::Attribute code) const; code为HttpStatusCodeAttribute,获取http的状态码
  4. QUrl url() const; 获取url
  5. 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();
}