QT HTTP服务器

由于项目需要,需要实现利用QT的写一个HTTP服务器,能够提供本地文件在同一网段中,供设备下载,故此,编写了一个小程序,来实习那该功能。

先看看效果:

在浏览器中输入http://localhost:8080可查看到界面中出现“你好,世界!”

当我们输入http://localhost:8080/file时,就可以看到我们可以将我们存放到本地的11.txt文件下下来。

话不多说,直接上代码:

.pro文件

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets network

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    httpserver.cpp

HEADERS += \
    httpserver.h

FORMS += \
    httpserver.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${T

.h文件

#ifndef HTTPSERVER_H
#define HTTPSERVER_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextStream>
#include <QDebug>
#include <QFile>  // 用于文件操作

QT_BEGIN_NAMESPACE
namespace Ui {
class HttpServer;
}
QT_END_NAMESPACE

class HttpServer : public QTcpServer
{
    Q_OBJECT

public:
    HttpServer(QWidget *parent = nullptr);
    ~HttpServer();

    void startServer(int port);             // 启动服务器,监听指定端口

private slots:
    void handleNewConnection();             // 处理新的客户端连接
    void handleClientRequest(QTcpSocket *clientSocket);  // 处理客户端请求

private:
    void sendResponse(QTcpSocket *clientSocket, const QString &response);  // 发送响应给客户端
    QString readFile(const QString &filePath);  // 读取文件内容
private:
    Ui::HttpServer *ui;
};
#endif // HTTPSERVER_H

.cpp文件

#include "httpserver.h"
#include "ui_httpserver.h"

HttpServer::HttpServer(QWidget *parent)
    : QTcpServer(parent)
    , ui(new Ui::HttpServer)
{
    //ui->setupUi(this);
    // 当有新的连接时,调用handleNewConnection槽
    connect(this, &QTcpServer::newConnection, this, &HttpServer::handleNewConnection);
}

HttpServer::~HttpServer()
{
    //delete ui;
    close();  // 关闭服务器
}

void HttpServer::startServer(int port)
{
    if (!listen(QHostAddress::Any, port))  // 监听所有网络接口的指定端口
    {
        qDebug() << "服务器启动失败!";
    }
    else
    {
        qDebug() << "服务器已启动,监听端口:" << port;
    }
}

void HttpServer::handleNewConnection()
{
    while (hasPendingConnections())  // 检查是否有待处理的连接
    {
        QTcpSocket *clientSocket = nextPendingConnection();  // 获取新的客户端连接
        connect(clientSocket, &QTcpSocket::readyRead, this, [this, clientSocket]() {
            handleClientRequest(clientSocket);  // 处理客户端请求
        });
    }
}

void HttpServer::handleClientRequest(QTcpSocket *clientSocket)
{
    QTextStream in(clientSocket);  // 从客户端读取数据
    QString request = in.readAll();  // 读取完整的请求内容

    qDebug() << "客户端请求:" << request;

    // 解析请求行(第一行)
    QStringList requestLines = request.split("\r\n");
    QStringList requestLine = requestLines.first().split(" ");
    QString method = requestLine[0];  // 请求方法(如GET)
    QString path = requestLine[1];    // 请求路径(如/)

    qDebug() << "请求方法" << method << "请求路径" << path;

    // 根据请求路径构造响应
    QString response;
  
    if (method == "GET")
    {
        if (path == "/")  // 请求根路径,返回默认页面
        {
            response = "HTTP/1.1 200 OK\r\n"
                       "Content-Type: text/html; charset=UTF-8\r\n"
                       "Connection: close\r\n"
                       "\r\n"
                       "<html><body><h1>你好,世界!</h1></body></html>";
        }
        else if (path == "/file")  // 请求/file路径,返回文件内容
        {
            QString filePath = "D:/11.txt";  // 指定文件路径
            QString fileContent = readFile(filePath);  // 读取文件内容

            if (!fileContent.isEmpty())  // 如果文件内容不为空
            {
                response = "HTTP/1.1 200 OK\r\n"
                           "Content-Type: text/plain; charset=UTF-8\r\n"
                           "Connection: close\r\n"
                           "\r\n"
                           + fileContent;  // 返回文件内容
            }
            else
            {
                // response = "HTTP/1.1 404 Not Found\r\n"
                //            "Content-Type: text/plain; charset=UTF-8\r\n"
                //            "Connection: close\r\n"
                //            "\r\n"
                //            "文件未找到";  // 文件未找到时返回404
            }
        }
        else  // 其他路径返回404
        {
            response = "HTTP/1.1 404 Not Found\r\n"
                       "Content-Type: text/plain; charset=UTF-8\r\n"
                       "Connection: close\r\n"
                       "\r\n"
                       "404 Not Found";
        }
    }
    else  // 不支持其他HTTP方法
    {
        response = "HTTP/1.1 405 Method Not Allowed\r\n"
                   "Content-Type: text/plain; charset=UTF-8\r\n"
                   "Connection: close\r\n"
                   "\r\n"
                   "不支持的请求方法";
    }
    ----------------------------------------------------------*/

    //能将数据正常的发送出去,通过HTTP的发送,上传文件
    if (method == "GET")
    {
        if (path == "/")  // 请求根路径,返回默认页面
        {
            response = "HTTP/1.1 200 OK\r\n"
                       "Content-Type: text/html; charset=UTF-8\r\n"
                       "Connection: close\r\n"
                       "\r\n"
                       "<html><body><h1>你好,世界!</h1></body></html>";
        }
        else if (path == "/file")  // 请求/file路径,返回文件内容
        {
            QString filePath = "D:/11.txt";  // 指定文件路径
            QString fileContent = readFile(filePath);  // 读取文件内容

            if (!fileContent.isEmpty())  // 如果文件内容不为空
            {
                response = "HTTP/1.1 200 OK\r\n"
                           "Content-Type: text/plain; charset=UTF-8\r\n"
                           "Content-Disposition: attachment; filename=\"11.txt\"\r\n"
                           "Connection: close\r\n"
                           "\r\n"
                           + fileContent;  // 返回文件内容
            }
            else
            {
                // response = "HTTP/1.1 404 Not Found\r\n"
                //            "Content-Type: text/plain; charset=UTF-8\r\n"
                //            "Connection: close\r\n"
                //            "\r\n"
                //            "文件未找到";  // 文件未找到时返回404
            }
        }
        else  // 其他路径返回404
        {
            response = "HTTP/1.1 404 Not Found\r\n"
                       "Content-Type: text/plain; charset=UTF-8\r\n"
                       "Connection: close\r\n"
                       "\r\n"
                       "404 Not Found";
        }
    }
    else  // 不支持其他HTTP方法
    {
        response = "HTTP/1.1 405 Method Not Allowed\r\n"
                   "Content-Type: text/plain; charset=UTF-8\r\n"
                   "Connection: close\r\n"
                   "\r\n"
                   "不支持的请求方法";
    }

    sendResponse(clientSocket, response);  // 发送响应给客户端
}

void HttpServer::sendResponse(QTcpSocket *clientSocket, const QString &response)
{
    QTextStream out(clientSocket);  // 创建文本流,用于向客户端发送数据
    out.setCodec("UTF-8");  // 设置编码为UTF-8,确保中文显示正常
    out << response;  // 写入响应内容
    out.flush();  // 确保数据被发送

    clientSocket->disconnectFromHost();  // 主动断开与客户端的连接

    // 检查套接字是否已经处于未连接状态
    if (clientSocket->state() != QAbstractSocket::UnconnectedState)
    {
        clientSocket->waitForDisconnected();  // 等待连接断开
    }

    clientSocket->deleteLater();  // 释放客户端套接字资源
}

QString HttpServer::readFile(const QString &filePath)
{
    QFile file(filePath);  // 创建文件对象
    if (!file.exists())  // 如果文件不存在
    {
        qDebug() << "文件不存在:" << filePath;
        return QString();  // 返回空字符串
    }

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))  // 打开文件
    {
        qDebug() << "无法打开文件" << filePath;
        return QString();  // 返回空字符串
    }

    QString content = file.readAll();  // 读取文件内容
    file.close();  // 关闭文件
    return content;  // 返回文件内容
}

main.cpp文件

#include "httpserver.h"

#include <QApplication>
#include "HttpServer.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    HttpServer server;  // 创建服务器对象
    server.startServer(8080);  // 启动服务器,监听8080端口
    return a.exec();
}

哈哈哈,进行简单的小修改,将代码补全,也能更好的将代码拷贝复制了。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值