QT编程之HTTP服务端与客户端技术

一、HTTP 服务器实现方案

  1. QtWebApp 集成

    • QtWebApp源码httpserver 目录导入项目,并在 .pro 文件中添加 include ($$PWD/httpserver/httpserver.pri)‌。
    • 配置 WebApp.ini 文件定义服务参数(IP、端口、线程池等),通过 HttpListener 类启动监听‌。
    • 自定义 RequestMapper 类处理不同 URL 路径的请求,继承 HttpRequestHandler 实现业务逻辑‌。
    • 详细使用方法参考:QtWebApp - wuyuan2011woaini - 博客园
  2. 原生 Qt 网络模块

    • 使用 QTcpServer 监听端口,通过 incomingConnection() 接收客户端连接‌。
    • 解析 HTTP 请求头(如 QByteArray 处理报文),动态生成响应内容(如 HTML/JSON)‌。

二、HTTP 客户端实现方案

Qt中的QNetworkAccessManager是网络请求管理的核心类,用于异步处理HTTP/HTTPS等协议通信。以下是其关键特性及使用方式:

1. ‌核心功能
  • 单例管理‌:整个Qt应用只需一个实例即可管理所有网络请求,负责维护代理、缓存等全局配置‌。
  • 请求调度‌:支持GET、POST、PUT、DELETE等标准HTTP方法,并通过队列管理并发请求(如HTTP协议默认同一主机/端口允许6个并发请求)‌。
2. ‌基本使用步骤
复制代码
// 创建实例
QNetworkAccessManager *manager = new QNetworkAccessManager(this);

// 发送GET请求示例
connect(manager, &QNetworkAccessManager::finished, this, [=](QNetworkReply *reply) {
    // 处理响应数据
    QByteArray data = reply->readAll();
    reply->deleteLater(); // 避免内存泄漏
});
manager->get(QNetworkRequest(QUrl("http://example.com")));

通过finished信号接收响应,使用QNetworkReply对象解析返回数据和元信息(如HTTP头)‌。

复制代码
QNetworkAccessManager manager;  
QUrl url("http://example.com/api/resource");  
QNetworkRequest request(url);  
  
// 添加鉴权信息(与 GET 请求相同)  
QByteArray authHeaderData = "Basic " + yourBase64EncodedAuthString;  
request.setRawHeader(QByteArray("Authorization"), authHeaderData);  
  
// 准备 POST 数据(这里只是一个简单的示例)  
QByteArray postData = "key1=value1&key2=value2";  
  
// 发送 POST 请求  
QNetworkReply *reply = manager.post(request, postData);
3. ‌异步处理与资源管理
  • 异步API‌:所有请求非阻塞主线程,通过信号槽机制通知完成状态‌。
  • 资源释放 ‌:需手动调用reply->deleteLater()释放QNetworkReply对象,不可在槽函数中直接delete‌。
4. ‌高级配置
  • 代理与缓存 ‌:可通过setProxy()setCache()方法设置全局代理及缓存策略‌。
  • SSL加密连接 ‌:使用connectToHostEncrypted()建立HTTPS连接,支持自定义SSL配置‌。
5. ‌错误处理

监听errorOccurred信号处理网络错误:

复制代码
connect(reply, &QNetworkReply::errorOccurred, [](QNetworkReply::NetworkError code) {
    qDebug() << "Error:" << code;
})‌;
6. ‌超时控制

通过QTimer实现异步请求超时机制:

复制代码
QTimer::singleShot(5000, ‌:ml-search[reply] {  // 5秒超时
    if (reply && reply->isRunning()) {
        reply->abort();
        qDebug() << "Request timeout";
    }
})‌;
7. ‌鉴权处理

在请求头中添加鉴权信息(如Authorization):

复制代码
QNetworkRequest request;
request.setRawHeader("Authorization", "Bearer token123");
manager->get(request)‌:ml-citation{ref="3" data="citationList"}。
8. ‌设置请求头

如果你需要设置请求头(例如,设置Content-Typeapplication/json):

复制代码
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

8. ‌同步阻塞网络请求

QEventLoop在接收网络返回内容结束之前,一直阻塞等待。

复制代码
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QDebug>

struct TestA {
    int data; // 示例数据
    // 其他字段
};
 
class NetworkManager : public QObject {
    Q_OBJECT
 
public:
    NetworkManager(QObject* parent = nullptr) : QObject(parent) {
        manager = new QNetworkAccessManager(this);
    }
 
    TestA getTestA() {
        QEventLoop loop;
        TestA result;
 
        // 发起网络请求
        QNetworkRequest request(QUrl("http://www.example.com"));
        QNetworkReply* reply = manager->get(request);
 
        // 连接槽函数解析数据
        connect(reply, &QNetworkReply::finished, [&]() {
            if (reply->error() == QNetworkReply::NoError) {
                QByteArray response = reply->readAll();
                result = parseResponse(response);
            } else {
                qWarning() << "Network error:" << reply->errorString();
            }
            reply->deleteLater();
            loop.quit();
        });
 
        // 阻塞等待网络请求完成
        loop.exec();
 
        return result;
    }
 
private:
    QNetworkAccessManager* manager;
 
    TestA parseResponse(const QByteArray& response) {
        TestA parsedData;
        // 假设解析为整数数据
        parsedData.data = QString(response).toInt();
        return parsedData;
    }
};

#include <QCoreApplication>
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
 
    NetworkManager networkManager;
    TestA data = networkManager.getTestA();
    qDebug() << "Received data:" << data.data;
 
    return a.exec();
}
9. ‌异步非阻塞网络请求

通过设置回调函数,将网络请求应答回调出去。

复制代码
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QDebug>
#include <functional>
 
struct TestA {
    int data; // 示例数据
    // 其他字段
};

class NetworkManager : public QObject {
    Q_OBJECT
 
public:
    using Callback = std::function<void(const TestA&)>;
 
    NetworkManager(QObject* parent = nullptr) : QObject(parent) {
        manager = new QNetworkAccessManager(this);
    }
 
    void getTestA(const Callback& callback) {
        // 发起网络请求
        QNetworkRequest request(QUrl("http://www.example.com"));
        QNetworkReply* reply = manager->get(request);
 
        // 连接槽函数解析数据
        connect(reply, &QNetworkReply::finished, this, [this, reply, callback]() {
            TestA result;
            if (reply->error() == QNetworkReply::NoError) {
                QByteArray response = reply->readAll();
                result = parseResponse(response);
            } else {
                qWarning() << "Network error:" << reply->errorString();
            }
            reply->deleteLater();
            callback(result);
        });
    }
 
private:
    QNetworkAccessManager* manager;
 
    TestA parseResponse(const QByteArray& response) {
        TestA parsedData;
        // 假设解析为整数数据
        parsedData.data = QString(response).toInt();
        return parsedData;
    }
};

#include <QCoreApplication>
 
void handleResult(const TestA& data) {
    qDebug() << "Received data:" << data.data;
    QCoreApplication::quit();
}
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
 
    NetworkManager networkManager;
    networkManager.getTestA(handleResult);
 
    return a.exec();
}
相关推荐
Wizard7971 小时前
在linux 系统下的qt 安装mqtt库
linux·运维·qt
无名之逆1 小时前
Hyperlane:Rust 生态中的轻量级高性能 HTTP 服务器库,助力现代 Web 开发
服务器·开发语言·前端·后端·http·面试·rust
江沉晚呤时1 小时前
使用 .NET Core 实现 RabbitMQ 消息队列的详细教程
开发语言·后端·c#·.netcore
大模型铲屎官1 小时前
从零精通机器学习:线性回归入门
开发语言·人工智能·python·算法·机器学习·回归·线性回归
搞不懂语言的程序员1 小时前
单例模式详解(java)
java·开发语言·单例模式
WangMing_X1 小时前
C#实现图像缩放与裁剪工具
开发语言·c#·图像
Python破壁人手记2 小时前
《我的Python觉醒之路》之转型Python(十五)——控制流
java·服务器·开发语言·网络·python
yuyuyuliang002 小时前
Qt SQL-1
sql·qt
siy23332 小时前
[c语言日寄]浮点数的排序
c语言·开发语言·数据结构·笔记·学习
天人合一peng2 小时前
C# PaddleOCR字符识别
开发语言·c#