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协议概述
    • 请求消息Request
    • 响应消息Response
  • Qt Network
    • 支持协议
    • 请求头
    • 响应状态码
    • 错误
    • 请求


HTTP协议概述

HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通常,由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 OK",以及返回的内容,如请求的文件、错误消息、或者其它信息。

  • HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
  • HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
    以下图表展示了HTTP协议通信流程:
    Qt - 高级网络操作 HTTP/FTP_第1张图片

请求消息Request

Qt - 高级网络操作 HTTP/FTP_第2张图片
Qt - 高级网络操作 HTTP/FTP_第3张图片

  • 请求行:Request 消息中的第一行,由请求方式、请求URL、HTTP协议及版本三部分组成。

  • 请求头:其中 Content-Type 指定了客户端发送的内容格式。例如:Content-Type: application/json,指客户端发送的内容格式为 Json。

  • 请求体:要发送的表单数据。

响应消息Response

Qt - 高级网络操作 HTTP/FTP_第4张图片
Qt - 高级网络操作 HTTP/FTP_第5张图片

  • 状态行:Response 消息中的第一行,由 HTTP 协议版本号、状态码、状态消息三部分组成。状态码用来告诉 HTTP 客户端,HTTP 服务器是否产生了预期的 Response。HTTP/1.1 中定义了 5 类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别:

    1XX:提示信息 - 表示请求已被成功接收,继续处理。
    2XX:成功 - 表示请求已被成功接收、理解、接受。
    3XX:重定向 - 要完成请求必须进行更进一步的处理。
    4XX:客户端错误 - 请求有语法错误或请求无法实现。
    5XX:服务器端错误 - 服务器未能实现合法的请求。

  • 响应头:其中 Content-Type 指定了服务器返回的内容格式。例如:Content-Type: application/json,指服务器返回的内容格式为 Json。

  • 响应体:服务器返回的内容。

这里只对 HTTP 协议只做了一些简单的介绍:详细说明Qt - 高级网络操作 HTTP/FTP_第6张图片

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 %d\n", 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 %d\n", 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


小白发文,欢迎指正

你可能感兴趣的