QTcpServer實現web靜態資源服務

槑孒發表於2024-09-11

使用 QTcpServer 實現web靜態資源服務

目標:

  1. 監聽 8080 埠,處理瀏覽器的 HTTP 請求。
  2. 預設返回 index.html,路徑 / 對應該檔案。
  3. 響應其他靜態檔案(HTML、CSS、JS、圖片等)。
  4. 檔案不存在時,返回 404 錯誤。

實現步驟:

  1. 啟動伺服器:使用 QTcpServer::listen(QHostAddress::Any, 8080) 監聽 8080 埠。
  2. 解析請求路徑:從 HTTP 請求中提取路徑。預設路徑 / 對應 /index.html
  3. 返回靜態檔案:讀取檔案並根據副檔名設定 Content-Type,然後透過 socket 返回內容。
  4. 錯誤處理:當檔案不存在時,返回 404 Not Found

示例程式碼:

#include <QTcpServer>
#include <QTcpSocket>
#include <QFile>
#include <QDir>

class HttpServer : public QTcpServer {
    Q_OBJECT

public:
    // 建構函式:啟動監聽8080埠
    HttpServer() {
        listen(QHostAddress::Any, 8080);
    }

protected:
    // 重寫incomingConnection,用於處理新連線
    void incomingConnection(qintptr socketDescriptor) override {
        QTcpSocket *socket = new QTcpSocket(this);
        socket->setSocketDescriptor(socketDescriptor); // 設定套接字描述符

        // 處理來自客戶端的請求
        connect(socket, &QTcpSocket::readyRead, this, [this, socket]() {
            QString request = socket->readAll();            // 讀取請求內容
            QString path = parseRequestPath(request);       // 解析請求路徑
            if (path.isEmpty() || path == "/") path = "/index.html"; // 預設返回index.html

            QString filePath = QDir::currentPath() + "/build" + path; // 構建檔案路徑
            QFile file(filePath);

            // 如果檔案存在並且可以開啟,傳送檔案內容
            if (file.exists() && file.open(QIODevice::ReadOnly)) {
                sendFile(socket, file, path);
            } else {
                // 檔案不存在,返回404錯誤
                socket->write("HTTP/1.1 404 Not Found\r\n\r\n");
            }

            socket->disconnectFromHost(); // 處理完成後斷開連線
        });

        // 斷開連線時,自動刪除socket物件
        connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
    }

private:
    // 解析HTTP請求,提取請求路徑
    QString parseRequestPath(const QString &request) {
        return request.split("\r\n").first().split(" ").value(1); // 解析第一行,提取路徑部分
    }

    // 傳送檔案內容給客戶端,並設定正確的Content-Type
    void sendFile(QTcpSocket *socket, QFile &file, const QString &path) {
        QByteArray response = "HTTP/1.1 200 OK\r\n"; // 構建HTTP響應頭
        if (path.endsWith(".html")) response += "Content-Type: text/html\r\n";
        else if (path.endsWith(".css")) response += "Content-Type: text/css\r\n";
        else if (path.endsWith(".js")) response += "Content-Type: application/javascript\r\n";
        response += "\r\n" + file.readAll(); // 讀取檔案內容並新增到響應體
        socket->write(response); // 傳送響應
    }
};

虛擬碼,僅提供參考!

說明:

  • 監聽埠 8080
  • 處理根路徑 /,返回 index.html
  • 支援靜態檔案型別(HTML、CSS、JS)。
  • 404 處理:檔案不存在返回 404 Not Found

總結:

使用 QTcpServer 實現了基本的 HTTP 請求處理,並且可以響應靜態檔案,用於前端專案打包後的靜態資源服務。

相關文章