Qt http

news2024/11/14 20:30:12

文章目录

  • 前言
    • 1. 定义的接口
    • 2.connect信号槽
    • 3. get
    • 4. get 下载文件
    • 5. post
  • 总结


前言

/*
1.请求报文:
请求报文是由客户端发送给服务器,用于请求特定资源或执行特定操作。它由以下几个部分组成:
请求行:描述了请求的方法、目标资源的路径和HTTP协议的版本,通常包含以下三个字段:

        请求方法:指定了客户端希望服务器执行的操作,如GET、POST、PUT、DELETE等。
请求目标:表示客户端希望访问的资源路径,可以是绝对路径或相对路径。
    协议版本:指定所使用的HTTP协议的版本,如HTTP/1.1。
请求头:包含了关于请求的附加信息,格式为键值对。常见的请求头字段包括:

Host:指定请求的目标主机。
User-Agent:标识发送请求的客户端应用程序。
Content-Type:指定请求正文的类型。
请求正文(可选):包含客户端发送给服务器的数据,通常在使用POST等方法时使用。

2.响应报文:
响应报文是服务器对客户端请求的回应,包含了所请求资源的数据或执行结果。它由以下几个部分组成:
状态行:描述了响应的状态,包含以下三个字段:

协议版本:指定所使用的HTTP协议的版本,如HTTP/1.1。
状态码:表示服务器对请求的处理结果,如200表示成功,404表示资源未找到。
状态信息:对状态码进行简短的解释说明。
响应头:包含了关于响应的附加信息,格式为键值对。常见的响应头字段包括:

Content-Type:指定响应正文的类型。
Content-Length:指定响应正文的长度。
Set-Cookie:在响应中设置Cookie。
响应正文:包含了服务器返回给客户端的数据,可以是HTML、JSON、文件等。

请求报文和响应报文的结构化文本格式使得客户端和服务器能够互相理解并进行有效的通信。
它们是HTTP通信的基础,用于传递请求和响应的相关信息

******************************************************
text/html 表示数据格式是 HTML
text/css 表示数据格式是 CSS
application/javascript 表示数据各式是 JavaScript
application/json 表示数据格式是 JSON
******************************************************

*/


1. 定义的接口

  1. public公共接口,用作单线程
  2. public slots公共槽函数,支持类对象调用,在哪个线程调用即在哪个线程运行
  3. signals 信号,通过调用信号的方式在其对应槽函数线程创建事件执行,用于多线程
public:
    bool get(QString url, QString &data, int timeout = 20000);

    bool post(QString url, QString &data, QByteArray jsonData, int timeout = 20000);

    bool getDownload(QString url, QString filePath, int timeout = 20000);


signals:
    void sgnGet(QString url, int timeout = 20000);

    void sgnPost(QString url,QByteArray jsonData, int timeout = 20000);

    void sgnGetDownload(QString url, QString filePath, int timeout = 20000);

    void Progress(qint64, qint64);

    void finished(QString data, bool result);

public slots:
    void gets(QString url, int timeout = 20000);

    void posts(QString url,QByteArray jsonData, int timeout = 20000);

    void getDownloads(QString url, QString filePath, int timeout = 20000);

2.connect信号槽

    connect(this, &Http::sgnGet, this, &Http::gets);
    connect(this, &Http::sgnGetDownload, this, &Http::getDownloads);
    connect(this, &Http::sgnPost, this, &Http::posts);

3. get

//! 通过信号槽的方式调动
void Http::gets(QString url, int timeout)
{
    QString data = "";
    bool rt = this->get(url, data, timeout);
    emit finished(data, rt);
}
//! get请求数据
bool Http::get(QString url, QString& data, int timeout)
{
    qDebug()<<"Http       QThread::currentThread() = "<<QThread::currentThread();
    int repeatSend = 0;
    // 三次请求失败结束请求数据
    while(!repeatGet(url, data, timeout))
    {
        if(++repeatSend >= 3) return false;
    }
    return true;
}
//!
bool Http::repeatGet(QString& url, QString& data, int& timeout)
{
    // 建立事件循环
    QEventLoop loop;
    //设置发送请求所需的信息
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));
    //管理网络请求和响应
    QNetworkAccessManager manager;
    connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
    // 超时检测
    QTimer timer;
    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    // 处理网络请求的响应数据
    QNetworkReply* pReply = manager.get(request);
    connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
    // 超时检测定时器启动
    timer.start((timeout > 0) ? timeout : 2000);
    //执行事件循环,直到退出循环再执行后面代码
    loop.exec();

    //! 退出事件循环,判断定时器是否触发,触发即超时
    if(!timer.isActive())
    {
        pReply->deleteLater();
        return false;
    }

    //! 未超时停止定时器
    timer.stop();
    //
    QNetworkReply::NetworkError err = pReply->error();
    if(err != QNetworkReply::NoError)
    {
        // 检测状态码
        int statusCode  = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug()<<"get error, statusCode = "<<statusCode;
        return false;
    }
    //
    data = QString::fromUtf8(pReply->readAll());
    pReply->deleteLater();
    return true;
}

执行代码:

QString data = "";
qDebug()<<"----------------------------------";
qDebug()<< "MainWindow QThread::currentThread() = "<< QThread::currentThread();
qDebug()<<data.size();
data.clear();
qDebug()<<"--------------- 1 ----------------";
http->get(QString("http://www.baidu.com"),data, 2000);
qDebug()<<data.size();
data.clear();
qDebug()<<"--------------- 2 ----------------";
http->gets(QString("http://www.baidu.com"), 2000);
qDebug()<<data.size();
data.clear();
qDebug()<<"--------------- 3 ----------------";
emit http->sgnGet(QString("http://www.baidu.com"), 2000);
qDebug()<<data.size();
qDebug()<<"----------------------------------";
// 保存HTTP响应内容
// 组装保存的文件名 文件名格式: 路径/年_月_日 小时_分_秒 httpfile.html
QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy_MM_dd hh_mm_ss");
QString filePath = ".";
QString fileName = filePath + '/' + current_date + " httpfile" + ".html";

QFile file(fileName);
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)){
    //qDebug() << "file open error!";
    return ;
}
QTextStream out(&file);
out.setCodec("UTF-8");
out<<data;
file.close();
data.clear();

通过信号槽是多线程且异步的

在这里插入图片描述

4. get 下载文件

void Http::getDownloads(QString url, QString filePath, int timeout)
{
    bool rt = this->getDownload(url, filePath, timeout);
    emit finished(filePath, rt);
}
bool Http::getDownload(QString url, QString filePath, int timeout)
{
    qDebug()<<"Http        QThread::currentThread() = "<<QThread::currentThread();
    int repeatSend = 0;
    //
    while(!repeatGetDownload(url, filePath, timeout))
    {
        if(++repeatSend >= 3) return false;
    }
    return true;
}
bool Http::repeatGetDownload(QString& url, const QString& filePath, const int& timeout)
{
    if(!pFile.isOpen()) pFile.setFileName(filePath);
    //
    QEventLoop loop;
    //
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    //
    QNetworkAccessManager manager;
    connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
    //
    QTimer timer;
    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    //
    QNetworkReply* pReply = manager.get(request);
    connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
    connect(pReply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
    //
    timer.start((timeout > 0) ? timeout : 20000);
    loop.exec(QEventLoop::ExcludeSocketNotifiers);
    disconnect(pReply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);

    //! 超时
    if(!timer.isActive())
    {
        pReply->deleteLater();
        return false;
    }else{
        timer.stop();
    }

    QNetworkReply::NetworkError err = pReply->error();
    if(err != QNetworkReply::NoError)
    {
        // 检测状态码
        int statusCode  = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug()<<"get error, statusCode = "<<statusCode;

        //! 重定向
        const QVariant redirectionTarget = pReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
        if(!redirectionTarget.isNull())
        {
            QUrl redirectedUrl = redirectionTarget.toUrl();
            url = redirectedUrl.toString();
        }

        return false;
    }

    connect(pReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(LoadProgress(qint64,qint64)));
    connect(pReply, &QNetworkReply::readyRead, this, &Http::readSave);
    loop.exec();

    return true;
}
void Http::readSave()
{
    QNetworkReply* pReply = (QNetworkReply*)sender();

    if(!pFile.isOpen())
    {
        //! save file
        if(!pFile.open(QIODevice::WriteOnly))
        {
            qDebug() << pFile.errorString();
        }
    }
    pFile.write(pReply->readAll());
}
void Http::LoadProgress(qint64 recved, qint64 total)
{
    QNetworkReply* pReply = (QNetworkReply*)sender();
    
    if(recved >= total)
    {
        pFile.close();
        pReply->deleteLater();
    }
}

执行代码

QString url = "https://1.as.dl.wireshark.org/win64/Wireshark-win64-4.0.10.exe";
url = "https://enigmaprotector.com/assets/files/enigma_en_demo.exe";

qDebug()<<"----------------------------------";
qDebug()<< "MainWindow QThread::currentThread() = "<< QThread::currentThread();
qDebug()<<"--------------- 1 ----------------";
QString path = "./enigma1.exe";
//http->getDownload(url, path, 4000);
qDebug()<<"--------------- 2 ----------------";
path = "./enigma2.exe";
//http->getDownloads(url, path, 4000);
qDebug()<<"--------------- 3 ----------------";
path = "./enigma3.exe";
emit http->sgnGetDownload(url, path, 4000);
qDebug()<<"----------------------------------";

在这里插入图片描述

5. post

没测试过

void Http::posts(QString url,QByteArray jsonData, int timeout)
{
    QString data;
    bool rt = this->post(url, data, jsonData, timeout);
    emit finished(data, rt);
}
//!
bool Http::post(QString url, QString& data, QByteArray jsonData, int timeout)
{
    int repeatSend = 0;
    //
    while(!repeatPost(url, data, jsonData, timeout))
    {
        ++repeatSend;
        if(++repeatSend >= 3)
            return false;
    }
    return true;
}

//
bool Http::repeatPost(QString& url, QString& data, QByteArray& jsonData, int& timeout)
{
    //
    QEventLoop loop;
    //
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml;charset=UTF-8");
    //
    QNetworkAccessManager manager;
    connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
    //
    QTimer timer;
    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    //
    QNetworkReply* pReply = manager.post(request, jsonData);
    connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
    //
    timer.start((timeout > 0) ? timeout : 2000);
    loop.exec();

    //! 超时
    if(!timer.isActive())
    {
        pReply->deleteLater();
        return false;
    }

    //!
    timer.stop();
    //
    QNetworkReply::NetworkError err = pReply->error();
    if(err != QNetworkReply::NoError)
    {
        //! 检测状态码
        int statusCode  = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug()<<"get error, statusCode = "<<statusCode;

        //! 重定向
        const QVariant redirectionTarget = pReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
        if(!redirectionTarget.isNull())
        {
            QUrl redirectedUrl = redirectionTarget.toUrl();
            url = redirectedUrl.toString();
        }
        return false;
    }
    //!
    data = QString::fromUtf8(pReply->readAll());
    pReply->deleteLater();
    return true;
}

总结

学啥记啥,好记性不如烂笔头!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1230261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

josef约瑟 闭锁继电器 LB-7DG 100V 50HZ 导轨安装

LB-7型闭锁继电器 闭锁继电器LB-7导轨安装 一、用途 LB-7型闭锁继电器(以下简称继电器)用于发电厂及变电所内高压母线带电时防止和接地刀闸。 二、结构和工作原理 1、继电器按整流式原理构成&#xff0c;该继电器由变压器、电阻器、整流桥、滤波电容、极化继电器及指示灯组…

关于漏洞:检测到目标SSL证书已过期【原理扫描】

这个漏洞是监听443端口的&#xff0c;如果我们是正式的网站且使用了https那么更新证书即可。 但是我的服务器上面几乎是个空服务器&#xff0c;谁会用443呢&#xff1f; 找不到谁用了那我就部署一个nginx&#xff0c;用nginx代理443&#xff0c;找个证书配一下呗。 然而当我…

学了这么久,你知道Python机器学习全流程是怎样的么?

万事开头难&#xff0c;首先Python机器学习整个流程的第一步就是学习Python这门编程语言的相关基础知识。 第一步&#xff1a;基本 Python 技能 如果要使用 Python 进行机器学习&#xff0c;拥有对 Python 有基础的理解非常关键。幸运的是&#xff0c;Python 是当前普遍使用的…

【Linux】Linux下的基础IO

❤️前言 大家好&#xff01;今天这篇博客和大家聊一聊关于Linux下的基础IO。 正文 在阅读本篇博客之前&#xff0c;请大家先回顾一下C语言文件操作的一些方法&#xff0c;这里可以看看我之前记录的一些内容&#xff1a; 【C语言】C语言成长之路之文件操作_MO_lion的博客-CSD…

移动端获取ua头的值

目录&#xff1a; 1、检测地址2、测试结果 1、检测地址 http://www.ip138.com/useragent/ 2、测试结果 成功的拿到了ua头的值了&#xff0c;亲测可行&#xff01;&#xff01;&#xff01;

红海营销时代,内容占位的出海品牌更有机会营销占位

#01 品牌出海&#xff1a;内容占位就是品牌营销占位 红海营销时代&#xff0c;内容信息充斥着用户周边。无论线上还是线下&#xff0c;生活工作、休闲娱乐等不同场景内&#xff0c;广告信息均无孔不入。对于用户来说&#xff0c;能记住的品牌或者商品往往寥寥无几。 占位营销…

Mysql超详细安装配置教程(保姆级)

目录 一、下载Mysql 二、安装Mysql 三、配置Mysql 四、连接Mysql 五、部分疑难问题 一、下载Mysql 从官网下载MySQL&#xff0c;这里我选用的是Mysql8.0.34版本 二、安装Mysql 下载完成后直接双击进行安装&#xff0c;打开后的页面如下所示&#xff1a; “Developer Defa…

二叉树题目:二叉树的最近公共祖先

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树的最近公共祖先 出处&#xff1a;236. 二叉树的最近公共祖先 难度 5 级 题目描述 要求 给定一个二叉树&…

【LeetCode刷题】--9.回文数

9.回文数 class Solution {public boolean isPalindrome(int x) {if(x < 0){return false;}int tmp x, sum 0;boolean flag false;while(x ! 0){sum sum * 10 x % 10;x / 10;}if(sum tmp){flag true;}return flag;} }

动画师如何选择全身动捕设备制作动画?

随着行业的不断发展&#xff0c;全身动捕设备在动画制作行业的应用已十分普遍。全身动捕设备分为光学动捕设备和惯性动捕设备&#xff0c;动画师该如何选择全身动捕设备制作动画&#xff1f; 与光学动捕设备相比&#xff0c;惯性动捕设备对场地和空间的限制更小&#xff0c;不…

vulnhub靶机Presidential

靶机地址&#xff1a;https://download.vulnhub.com/presidential/Presidential.ova 主机发现 arp-scan -l 端口扫描 nmap --min-rate 10000 192.168.21.150 端口服务扫描 nmap -sV -sT -O -p80 192.168.21.150 漏洞扫描 nmap --scriptvuln -p80 192.168.21.150 只有一个端…

NodeMCU ESP8266构建Web Server网页端控制设备

NodeMCU ESP8266构建Web Server网页端控制设备 前言 NodeMCU ESP8266 内部集成了TCP/IP协议栈&#xff0c;可以快速构建网络功能&#xff0c;搭建联网应用的硬件平台&#xff1b; ESP8266可以作为WiFi接入点&#xff08;Station&#xff09;&#xff0c;这样可以方便连接互联…

如何修改dpi为300?96dpi怎么改成300dpi?

平时使用的图片dpi一般都是96&#xff0c;但是我们在打印的时候&#xff0c;都要求dpi为300以上&#xff0c;这时候就需要修改图片分辨率&#xff0c;如何改图片分辨率成了一个问题&#xff0c;所以今天就教大家一个图片分辨率提高在线处理的方法&#xff0c;一起来了解一下吧。…

右键菜单和弹出菜单的区别

接触windows开发10年了&#xff0c;一直以为"右键菜单"和"弹出菜单"是不同的。 最近刚刚发现&#xff0c;这两种菜单在定义的时候和消息循环处理程序中并没有什么不同&#xff0c;区别只是在于windows底层显示方式。 如下是右键菜单的显示方式&#xff1…

【图像分类】【深度学习】【Pytorch版本】GoogLeNet(InceptionV4)模型算法详解

【图像分类】【深度学习】【Pytorch版本】GoogLeNet(InceptionV4)模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】GoogLeNet(InceptionV4)模型算法详解前言GoogLeNet(InceptionV4)讲解Stem结构Inception-A结构Inception- B结构Inception-C结构redution-A结构re…

4-1三个整数的最大数

#include<stdio.h> int main(){int a,b,c,t,max;printf("请输入三个数&#xff1a;");scanf("%d,%d,%d",&a,&b,&c);t(a>b)?a:b;max(t>c)?t:c;printf("输出三个数中最大是数字是&#xff1a;%d",max);return 0;}

单链表相关面试题--3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

/* 解题思路&#xff1a; 通过快慢指针找到中间节点&#xff0c;快指针每次走两步&#xff0c;慢指针每次走一步&#xff0c;当快指针走到结尾的时候&#xff0c;慢指针正好走到中间位置 */ typedef struct ListNode Node; struct ListNode* middleNode(struct ListNode* head)…

全面解读数据资产入表风口,与企业有什么关系和影响

亿信华辰『数据资产入表实务系列直播』第一期成功举办。我们邀请到了亿信华辰高级顾问专家、湖北省软件企业协会数据要素发展工作委员会专家委员刘晗为大家带来数据入表知识体系分享&#xff0c;全程干货&#xff0c;深度解读&#xff0c;以下是演讲上半部分直播内容。 一、数据…

Netty源码学习4——服务端是处理新连接的netty的reactor模式

零丶引入 在前面的源码学习中&#xff0c;梳理了服务端的启动&#xff0c;以及NioEventLoop事件循环的工作流程&#xff0c;并了解了Netty处理网络io重要的Channel &#xff0c;ChannelHandler&#xff0c;ChannelPipeline。 这一篇将学习服务端是如何构建新的连接。 一丶网络包…

​使用SPDK lib搭建自己的NVMe-oF Target应用​

一. 背景 NVMe是一种抽象的传输协议层&#xff0c;旨在提供可靠的NVMe命令和数据传输。NVMe over Fabric (NVMe-oF) 实现了NVMe标准在PCIe总线上的扩展&#xff0c;可以支持数据中心的网络存储&#xff0c;它支持多种传输方式包括FC&#xff0c;RDMA和TCP。NVMe-oF服务(应用) 是…