Qt – 高级网络操作 HTTP/FTP
欢迎转载,请注明出处:https://blog.csdn.net/qq_39453936?spm=1010.2135.3001.5343
原文链接: https://blog.csdn.net/qq_39453936/article/details/121401436
高级网络操作 HTTP和FTP
HTTP协议概述
HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通常,由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 OK",以及返回的内容,如请求的文件、错误消息、或者其它信息。
- HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
- HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
以下图表展示了HTTP协议通信流程:
请求消息Request
-
请求行:Request 消息中的第一行,由请求方式、请求URL、HTTP协议及版本三部分组成。
-
请求头:其中 Content-Type 指定了客户端发送的内容格式。例如:Content-Type: application/json,指客户端发送的内容格式为 Json。
-
请求体:要发送的表单数据。
响应消息Response
-
状态行:Response 消息中的第一行,由 HTTP 协议版本号、状态码、状态消息三部分组成。状态码用来告诉 HTTP 客户端,HTTP 服务器是否产生了预期的 Response。HTTP/1.1 中定义了 5 类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别:
1XX:提示信息 - 表示请求已被成功接收,继续处理。
2XX:成功 - 表示请求已被成功接收、理解、接受。
3XX:重定向 - 要完成请求必须进行更进一步的处理。
4XX:客户端错误 - 请求有语法错误或请求无法实现。
5XX:服务器端错误 - 服务器未能实现合法的请求。 -
响应头:其中 Content-Type 指定了服务器返回的内容格式。例如:Content-Type: application/json,指服务器返回的内容格式为 Json。
-
响应体:服务器返回的内容。
这里只对 HTTP 协议只做了一些简单的介绍:详细说明
Qt Network
Qt Network 模块提供了大量的API用于网络操作。API为特定的操作和协议提供了一个抽象层(如通过HTTP收发数据)。并且仅公开一般或高级概念的类、函数和信号。
-
QNetworkRequest 网络请求:,充当与请求相关联的信息的通用容器,例如请求头信息、加密等。构造请求对象时指定的URL确定用于请求的协议。目前,支持HTTP、FTP和本地文件URL上传和下载。
-
QNetworkAccessManager操作管理:请求创建后,管理类会分发请求,然后对外发送信号标识请求进度。还可使用cookies在客户端存储数据、请求认证、代理使用。
-
QNetworkReply请求响应;该对象由QNetworkAccessManager在发送请求时创建。QNetworkReply提供的信号可以用于单独监控每个请求响应,或者开发人员可以选择使用管理器QNetworkAccessManager的信号来代替,并放弃对请求响应的引用。由于QNetworkReply是QIODevice的一个子类,因此响应可以被同步或异步的处理(阻塞或非阻塞)。
每个应用程序或库都可以创建一个或多个QNetworkAccessManager实例来处理网络通信。
支持协议
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
qDebug() << manager->supportedSchemes();
列出支持的所有 URL schemes:
(“ftp”, “file”, “qrc”, “http”, “https”, “data”)
请求头
如果你想为请求添加 HTTP 头部,只要简单地调用 setHeader() 就可以了。
例如,发送的请求时,使用的 User-Agent 是 Mozilla/5.0 , 为了方便以后追踪版本信息,可以将软件的版本信息写入到 User-Agent 中。
QNetworkRequest request;
request.setHeader(QNetworkRequest::UserAgentHeader, "my-app/0.0.1");
当然,除了 User-Agent 之外,QNetworkRequest::KnownHeaders 还包含其他请求头,它就是为 HTTP 头部而生的。根据 RFC 2616, HTTP 头部是大小写不敏感。
如果 QNetworkRequest::KnownHeaders 不满足需要,使用 setRawHeader()。
响应状态码
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (statusCode .isValid())
qDebug() << variant.toInt();
statusCode是HTTP服务器的相应码参考;最常见的是 200 OK,表示请求已成功,请求所希望的响应头或数据体将随此响应返回。
错误
如果请求的处理过程中遇到错误(如:DNS 查询失败、拒绝连接等)时,则会产生一个 QNetworkReply::NetworkError。错误定义参考;
请求
-
get请求
void getRequest() { QNetworkAccessManager *manager = new QNetworkAccessManager(); //设置url QString url = "https://www.csdn.net/"; QNetworkRequest request; request.setUrl(QUrl(url)); //添加事件循环机制,请求过程为异步,返回后再执行后面的 QEventLoop eventLoop; QNetworkReply *reply = manager->get(request); connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); eventLoop.exec(); //错误处理 if (reply->error() == QNetworkReply::NoError) { qDebug() << "success"; } else { qDebug()<<"failure"; QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); qDebug( "request error code: %d %dn", statusCode.toInt(), (int)reply->error()); qDebug(qPrintable(reply->errorString())); } //请求返回的结果 QByteArray responseByte = reply->readAll(); qDebug() << responseByte; }
-
post请求
void postRequest() { QNetworkAccessManager *manager = new QNetworkAccessManager(); //设置url QString url = "https://www.csdn.net/"; QNetworkRequest request; request.setUrl(QUrl(url)); request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json")); // request.setRawHeader("Content-Type","application/json");//服务器要求的数据头部 // request.setRawHeader("Accept","text/json,*/*;q=0.5");//服务器要求的数据头部 //添加事件循环机制,请求过程为异步,返回后再执行后面的 QEventLoop eventLoop; //发送数据 QByteArray qByteHttpData = JsonData(); QNetworkReply *reply = manager->post(requestInfo, qByteHttpData); connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); eventLoop.exec(); //错误处理 if (reply->error() == QNetworkReply::NoError) { qDebug() << "success"; } else { qDebug()<<"failure"; QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); qDebug( "request error code: %d %dn", statusCode.toInt(), (int)reply->error()); qDebug(qPrintable(reply->errorString())); } //请求收到的结果 QByteArray responseByte = reply->readAll(); qDebug() << responseByte; }
注意:开启事件循环时,界面不会响应用户操作(界面被阻塞)
参考文章:
https://blog.csdn.net/liang19890820/article/details/52535755/
https://www.runoob.com/http/http-methods.html
小白发文,欢迎指正