zoukankan      html  css  js  c++  java
  • 第九课、Qt之高级网络操作(HTTP/FTP快速上手)

    一、 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)、响应体:服务器返回的内容

    这里写图片描述

    二、支持的协议

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

    输出结果

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

    三、请求

    // 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;

    四、更加复杂的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);

    这里写图片描述

    五、可以使用 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);

    这里写图片描述

    六、定制请求头

    (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:包含发出请求的用户信息。

    这里写图片描述

    七、响应内容

    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 状态码请参考:

    (2)、最常见的是 200 OK,表示请求已成功,请求所希望的响应头或数据体将随此响应返回

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

    3、响应头

    进入 Response Headers:

    这里写图片描述

    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("未知错误");
    }
    // "远程主机名未找到(无效主机名)"
  • 相关阅读:
    键盘ASCII码
    Pandas常用功能总结
    TensorFlow之多核GPU的并行运算
    Linux中目录以及路径问题
    菜鸟的服务器进阶
    ORA-02447: cannot defer a constraint that is not deferrable
    ORA-25153: Temporary Tablespace is Empty解决方法
    查询当前会话进程号
    Oracle中的USEREVN()
    Oracle物理结构与逻辑结构
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6481735.html
Copyright © 2011-2022 走看看