Qt での HTTP クライアントおよびサーバー実装

HTTP プロトコルの概要

HTTP(HyperText Transfer Protocol)は、クライアントとサーバー間でリクエストとレスポンスを交換するためのプロトコルであり、通常は TCP 上で動作します。このプロトコルは、Web ブラウザとサーバー間の通信ルールを定義し、情報の送受信を標準化します。

HTTP の基本的な処理フローは以下の通りです:

  1. クライアントがサーバーとの TCP 接続を確立する。
  2. クライアントが HTTP リクエストを送信する。
  3. サーバーがリクエストを処理し、HTTP レスポンスを返す。
  4. 通信終了後に接続が切断される。

Qt を使った HTTP 実装例

1. HTTP クライアントの実装

Qt の QNetworkAccessManager を使用して、HTTP GET リクエストを送信し、レスポンスを取得するシンプルなクライアントアプリケーションです。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_fetchButton_clicked();
    void handleNetworkResponse(QNetworkReply *reply);

private:
    Ui::MainWindow *ui;
    QNetworkAccessManager *networkManager;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    networkManager = new QNetworkAccessManager(this);
    connect(networkManager, &QNetworkAccessManager::finished,
            this, &MainWindow::handleNetworkResponse);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_fetchButton_clicked()
{
    ui->statusLabel->setText("データ取得中...");
    QNetworkRequest request(QUrl("http://www.baidu.com"));
    networkManager->get(request);
}

void MainWindow::handleNetworkResponse(QNetworkReply *reply)
{
    if (reply->error() == QNetworkReply::NoError) {
        ui->resultBrowser->setPlainText(reply->readAll());
    } else {
        ui->resultBrowser->setPlainText("エラー: " + reply->errorString());
    }
    reply->deleteLater();
}

2. 簡易 HTTP サーバーの実装

QTcpServerQTcpSocket を使って、静的 HTML コンテンツを返す最小限の HTTP サーバーを構築します。

// httpserver.h
#ifndef HTTPSERVER_H
#define HTTPSERVER_H

#include <QObject>
#include <QTcpServer>

class HttpServer : public QObject
{
    Q_OBJECT

public:
    explicit HttpServer(QObject *parent = nullptr);
    ~HttpServer();

private slots:
    void handleNewConnection();

private:
    QTcpServer *tcpServer;
};
#endif // HTTPSERVER_H
// httpserver.cpp
#include "httpserver.h"
#include <QTcpSocket>
#include <QDateTime>
#include <QDebug>

HttpServer::HttpServer(QObject *parent)
    : QObject(parent)
{
    tcpServer = new QTcpServer(this);
    connect(tcpServer, &QTcpServer::newConnection,
            this, &HttpServer::handleNewConnection);

    if (!tcpServer->listen(QHostAddress::Any, 8088)) {
        qWarning() << "サーバー起動失敗:" << tcpServer->errorString();
    } else {
        qDebug() << "サーバーがポート 8088 で待機中...";
    }
}

HttpServer::~HttpServer()
{
    tcpServer->close();
}

void HttpServer::handleNewConnection()
{
    static int visitCount = 0;
    QTcpSocket *clientSocket = tcpServer->nextPendingConnection();

    // リクエスト読み捨て(簡易実装のため)
    clientSocket->waitForReadyRead(100);
    clientSocket->readAll();

    QString httpResponse =
        "HTTP/1.1 200 OK\r\n"
        "Content-Type: text/html; charset=utf-8\r\n"
        "Refresh: 1\r\n"
        "\r\n"
        "<!DOCTYPE html>"
        "<html>"
        "<head><title>Qt HTTP Server</title></head>"
        "<body>"
        "<h2>Qt で実装した簡易 HTTP サーバー</h2>"
        "<p>アクセス回数: " + QString::number(++visitCount) + "</p>"
        "<p>現在時刻: " + QDateTime::currentDateTime().toString() + "</p>"
        "</body>"
        "</html>";

    clientSocket->write(httpResponse.toUtf8());
    clientSocket->flush();
    clientSocket->disconnectFromHost();
    connect(clientSocket, &QTcpSocket::disconnected,
            clientSocket, &QTcpSocket::deleteLater);
}
// main.cpp
#include <QCoreApplication>
#include "httpserver.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    HttpServer server;
    return app.exec();
}

タグ: Qt HTTP QNetworkAccessManager QTcpServer C++

7月20日 00:38 投稿