第九课、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("未知错误");
}
// "远程主机名未找到(无效主机名)"
时间: 2024-08-28 07:02:06

第九课、Qt之高级网络操作(HTTP/FTP快速上手)的相关文章

第32课 Qt中的文件操作

1. Qt的中IO操作 (1)Qt中IO操作的处理方式 ①Qt通过统一的接口简化了文件和外部设备的操作方式 ②Qt中的文件被看作一种特殊的外部设备 ③Qt中的文件操作与外部设备的操作相同 (2)IO操作中的关键函数接口——IO操作的本质:连续存储空间的数据读写 ①打开设备:bool open(OpenMode mode); ②读取数据:QByteArray read(qint64 maxSize); ③写入数据:qint64 write(const QByteArray& byteArray);

第5章 高级网络操作

半开放socket 通常socket是双向的,有时你会想建立一个单向的socket,单向的socket被称为半开放socket.为此,需要调用shutdown()函数,对于socket,这个操作是不可逆的.半开放socket可以用于一下情况: 你想要确保所有写好的数据都已经被传送出去.当为了关闭socket的输出频道而调用shutdown()函数的时候,只有在缓存里面的数据都被成功发送出去后,才会有返回. 你想有个办法来捕获潜在的程序错误,这些错误是由数图写一个不能写的socket,或者读一个不

第三十二课、Qt中的文件操作

一.Qt中的IO操作 1.Qt中IO操作的处理方式 (1).Qt通过统一的接口简化了文件与外部设备的操作方式 (2).Qt中的文件被看做是一种特殊的外部设备 (3).Qt中的文件操作与外部设备操作相同 2.IO操作中的关键函数接口 注意:IO操作的本质:连续存储空间的数据读写 3.Qt中IO设备类型 (1).顺序存储设备:只能从头开始顺序读写数据,不能指定数据的读写位置(串口) (2).随机存储设备:可以定位到任意位置进行数据读写(seek function函数)(文件) 4.Qt中IO设备 的

【Linux探索之旅】第二部分第九课:查找文件,无所遁形

内容简介 1.第二部分第九课:查找文件,无所遁形 2.第二部分测试题 查找文件,无所遁形 这一课不难,但挺重要的. 之前的课程我们见识过了Linux下文件的组织形式是很特别的,跟Windows不一样. 我们也用ls / 这个命令来列出根目录下的所有目录,有/bin,/etc,/var,/home,等等.而这些目录下又有子目录和文件,错综复杂. 这些目录中有一部分是历史遗留的,从Unix时代就有了.问题是:我们如何在这"茫茫文海"中查找我们需要的文件. "人潮人海中,有你有我.

【C语言探索之旅】 第一部分第九课:函数

内容简介 1.课程大纲 2.第一部分第九课:函数 3.第一部分第十课预告: 练习题+习作 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算那点事 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量类型 文件读写 动

Qt 多线程和网络编程学习

一,Qt多线程类学习 QThread类,开始一个新的线程就是开始执行重新实现QThread::run(),run()是默认现实调用exec(),QThread::start()开始线程的执行,run()函数是在start()函数调用之后开始执行 QMutex类,互斥量/互斥锁,加锁解锁,原子操作 QWaitCondition类,一个线程在一定条件下等待其它线程的唤醒,在此之前一直处于休眠期.QWaitCondition::wakeOne()随机唤醒一个等待的线程,QWaitCondition::

基于案例SQL优化第九课作业分享

默认统计信息收集: 1. 11g默认启动了统计信息收集的任务,默认运行时间是周一到周五晚上10点和周6,周天的早上6点 2. 你也可以关闭自动统计新收集任务,选择手工收集的方式,但是一般不建议这样操作. 动态统计信息: 1. 统计信息默认情况下是每天晚上10点半后收集,如果新建对象还没来得级收集统计信息,就采用动态采样的方式. 2. 具体在set autotrace 跟踪的执行计划中,可以看到类似:- dynamic sampling used for this statement (level

ClouStack4.5(高级网络模式)+Xen

一.环境 1.软件信息 名称 版本 备注 CloudStack 4.5.x Centos 6.7 Mysql 5.x 系统自带 Tomcat 6.x/7.x 系统自带 XenServer 6.5 2.硬件信息 名称 配置 类型 IP 数量 CloudStack 管理节点 2C/4G 管理节点 192.168.16.242 1 XenServer 4C/8G 资源节点 192.168.16.245/246 2 NFS存储 2c/4G 存储节点 192.168.16.247 1 3.网络信息 CS中

Qt之实现网络下发配置的半透明友好提示界面

一.说明 在使用Qt开发的网管客户端程序中,网管客户端主要负责显示设备信息以及对设备下发配置信息等,如配置设备名字.更新设备程序等:由于在网管客户端程序的操作要先经过服务器处理,再由服务器将该命令转发给设备,因此网管客户端程序和设备之间是通过网络通信交互的:这样就会出现很多不稳定的情况,如网络连接断开.下发配置超时.下发配置失败.下发配置成功等等:然而所有如上的操作结果都需要反馈到网管客户端程序对用户进行友好的提示:该博文主要讲述如何实现这一流程. 二.界面设想 界面设想以及要求如下所示: 有一