天天看點

Qt之進階網絡操作(HTTP/FTP快速上手)

作者:音視訊開發老舅

1、 HTTP 的消息結構

1、Request

(1)、請求行:Request 消息中的第一行,由請求方式、請求URL、HTTP協定及版本三部分組成

(2)、請求頭:其中 Content-Type 指定了用戶端發送的内容格式。例如:Content-Type: application/json,指用戶端發送的内容格式為 Json

(3)、請求體:要發送的表單資料

2、Response

(1)、狀态行:Response 消息中的第一行,由 HTTP 協定版本号、狀态碼、狀态消息三部分組成。狀态碼用來告訴 HTTP 用戶端,HTTP 伺服器是否産生了預期的 Response。HTTP/1.1 中定義了 5 類狀态碼, 狀态碼由三位數字組成,第一個數字定義了響應的類别:

A、1XX:提示資訊 - 表示請求已被成功接收,繼續處理

B、2XX:成功 - 表示請求已被成功接收、了解、接受

C、3XX:重定向 - 要完成請求必須進行更進一步的處理

D、4XX:用戶端錯誤 - 請求有文法錯誤或請求無法實作

E、5XX:伺服器端錯誤 - 伺服器未能實作合法的請求

(2)、響應頭:其中 Content-Type 指定了伺服器傳回的内容格式。例如:Content-Type: application/json,指伺服器傳回的内容格式為 Json

(3)、響應體:伺服器傳回的内容

Qt之進階網絡操作(HTTP/FTP快速上手)

2、支援的協定

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
qDebug() << manager->supportedSchemes();           

輸出結果

(“ftp”, “file”, “qrc”, “http”, “https”, “data”)           

3、請求

// URL
QString baseUrl = "http://www.csdn.net/";

// 構造請求
QNetworkRequest request;
request.setUrl(QUrl(baseUrl));

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
// 發送請求
QNetworkReply *pReplay = manager->get(request);

// 開啟一個局部的事件循環,等待響應結束,退出
QEventLoop eventLoop;
QObject::connect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
eventLoop.exec();

// 擷取響應資訊
QByteArray bytes = pReplay->readAll();
qDebug() << bytes;           

4、更加複雜的POST請求

(1)、傳遞一個QByteArray 給 data 參數

(2)、資料在送出請求時會自動編碼為表單形式

// URL
QString baseUrl = "http://httpbin.org/post";
QUrl url(baseUrl);

// 表單資料
QByteArray dataArray;
dataArray.append("key1=value1&");
dataArray.append("key2=value2");

// 構造請求
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setUrl(url);

QNetworkAccessManager *manager = new QNetworkAccessManager(this);

// 發送請求
manager->post(request, dataArray);           
Qt之進階網絡操作(HTTP/FTP快速上手)

5、可以使用 json 參數直接傳遞,然後它就會被自動編碼

// URL
QString baseUrl = "http://httpbin.org/post";
QUrl url(baseUrl);

// Json資料
QJsonObject json;
json.insert("User", "Qter");
json.insert("Password", "123456");

QJsonDocument document;
document.setObject(json);
QByteArray dataArray = document.toJson(QJsonDocument::Compact);

// 構造請求
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setUrl(url);

QNetworkAccessManager *manager = new QNetworkAccessManager(this);

// 連接配接信号槽
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinished(QNetworkReply *)));

// 發送請求
manager->post(request, dataArray);           
Qt之進階網絡操作(HTTP/FTP快速上手)

6、定制請求頭

(1)如果你想為請求添加 HTTP 頭部,隻要簡單地調用 setHeader() 就可以了。

(2)如發送的請求時,使用的 User-Agent 是 Mozilla/5.0 , 為了友善以後追蹤版本資訊,可以将軟體的版本資訊寫入到 User-Agent 中

(3)、除了 User-Agent 之外,QNetworkRequest::KnownHeaders 還包含其他請求頭,它就是為 HTTP 頭部而生的。根據 RFC 2616, HTTP 頭部是大小寫不敏感。

(4)、如果 QNetworkRequest::KnownHeaders 不滿足需要,使用 setRawHeader()

QNetworkRequest request;
request.setHeader(QNetworkRequest::UserAgentHeader, "my-app/0.0.1");           

User-Agent:包含送出請求的使用者資訊。

Qt之進階網絡操作(HTTP/FTP快速上手)

7、響應内容

1、響應内容

(1)、要擷取響應的内容,可以調用 readAll(),由于上述的 POST 請求傳回的資料為 Json 格式,将響應結果先轉化為 Json,然後再對其解析

(2)、響應的内容可以是 HTML 頁面,也可以是字元串、Json、XML等。最上面所發送的 GET 請求 擷取的就是 CSDN 的首頁 HTML

void replyFinished(QNetworkReply *reply)
{
    // 擷取響應資訊
    QByteArray bytes = reply->readAll();

    QJsonParseError jsonError;
    QJsonDocument doucment = QJsonDocument::fromJson(bytes, &jsonError);
    if (jsonError.error != QJsonParseError::NoError) {
        qDebug() << QStringLiteral("解析Json失敗");
        return;
    }

    // 解析Json
    if (doucment.isObject()) {
        QJsonObject obj = doucment.object();
        QJsonValue value;
        if (obj.contains("data")) {
            value = obj.take("data");
            if (value.isString()) {
                QString data = value.toString();
                qDebug() << data;
            }
        }
    }
}           

2、響應狀态碼

(1)、HTTP 狀态碼請參考:

  • Status codes
  • List of HTTP status codes

(2)、最常見的是 200 OK,表示請求已成功,請求所希望的響應頭或資料體将随此響應傳回

【領QT開發教程學習資料,點選→「連結」←莬費領取,先碼住不迷路~】

QVariant variant = pReplay->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (variant.isValid())
    qDebug() << variant.toInt();
// 200               

3、響應頭

進入 Response Headers:

Qt之進階網絡操作(HTTP/FTP快速上手)
QVariant variant = pReplay->header(QNetworkRequest::ContentTypeHeader);
if (variant.isValid())
    qDebug() << variant.toString();
// "text/html; charset=utf-8"           

4、錯誤

QNetworkReply::NetworkError error = pReplay->error();
switch (error) {
case QNetworkReply::ConnectionRefusedError:
    qDebug() << QStringLiteral("遠端伺服器拒絕連接配接");
    break;
case QNetworkReply::HostNotFoundError:
    qDebug() << QStringLiteral("遠端主機名未找到(無效主機名)");
    break;
case QNetworkReply::TooManyRedirectsError:
    qDebug() << QStringLiteral("請求超過了設定的最大重定向次數");
    break;
deafult:
    qDebug() << QStringLiteral("未知錯誤");
}
// "遠端主機名未找到(無效主機名)"           

繼續閱讀