読み込み中...

C++で学ぶWebSocket通信入門!初心者から上級者まで役立つ5つのサンプルコード

C++とWebSocketを使用した通信の概念図 C++
この記事は約21分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

C++でWebSocket通信を学ぶことは、プログラミングの世界において非常に重要なスキルです。

この技術を理解し、適切に使用することで、リアルタイムのデータ交換が可能なアプリケーションを開発することができます。

WebSocketは、ウェブベースの通信において重要な役割を担っており、多くの現代的なインターネットアプリケーションにおいて利用されています。

C++を使用したWebSocket通信の学習は、プログラミングの基本的な知識から始めることが可能です。

初心者にとっても理解しやすい基礎から、上級者にとっての応用的な内容まで、幅広くカバーすることが大切です。

この記事では、C++によるWebSocket通信の基本から応用までを詳細に解説し、実践的な理解を深めることを目的としています。

●C++とWebSocket通信の基本

C++を用いたWebSocket通信の基本を理解するには、まずWebSocketとは何か、そしてそれがどのように機能するのかを把握することが必要です。

WebSocketは、双方向通信を可能にするプロトコルの一つで、HTTPとは異なり、サーバーとクライアント間での継続的な通信が可能です。

これにより、リアルタイムのデータ交換や、高速なメッセージングが実現されます。

C++でWebSocket通信を実装する際には、適切なライブラリの選択が重要です。C++には様々なWebSocketライブラリが存在し、それぞれに特徴や利点があります。

選択するライブラリによって、実装の複雑さやパフォーマンス、サポートされている機能が異なりますので、プロジェクトの要件に合わせた適切なライブラリを選ぶことが肝要です。

○WebSocket通信とは

WebSocket通信とは、インターネット上でリアルタイムの双方向通信を行うための技術です。

従来のHTTP通信では、クライアントがサーバーにリクエストを送り、サーバーがレスポンスを返すという一方向の通信が基本でした。

しかし、WebSocketを使用すると、サーバーとクライアント間で接続が確立されると、その接続を維持したまま、双方向にデータを送受信することができます。

WebSocket通信の利点は、そのリアルタイム性にあります。

例えば、チャットアプリケーションやオンラインゲーム、金融市場のリアルタイムデータフィードなど、即時性が求められるアプリケーションにおいては、WebSocket通信が重要な役割を果たします。

また、WebSocketは標準化されたプロトコルであるため、多くのプログラミング言語やフレームワークでサポートされています。

○C++でのWebSocket通信の準備

C++でWebSocket通信を行うには、まずWebSocketプロトコルをサポートするライブラリを選択し、それをプロジェクトに組み込む必要があります。

C++には多くのWebSocketライブラリが存在し、それぞれに特性や性能、利用の容易さが異なります。

例えば、「WebSocket++」や「Boost.Beast」などが有名で、広く使用されています。

ライブラリを選択した後は、開発環境のセットアップが必要です。

C++の開発環境は、WindowsではVisual Studio、LinuxではGCCやClangなどがよく使われます。

また、WebSocketライブラリによっては、追加の依存関係がある場合もありますので、ドキュメントを参照し、必要なライブラリやツールをインストールすることが重要です。

C++でのWebSocket通信の準備段階では、基本的なプログラミングの知識に加え、ネットワークプログラミングの基礎についても理解しておくと良いでしょう。

ネットワークプログラミングには、IPアドレス、ポート番号、プロトコルなどの概念が含まれます。

これらの基礎を理解することで、WebSocketをより効果的に活用できるようになります。

●WebSocket通信の基本的な使い方

WebSocket通信の基本的な使い方を理解するには、まずWebSocketとは何か、そしてどのようにしてC++でWebSocket通信を行うのかを把握することが重要です。

WebSocketは、ウェブブラウザとサーバ間で双方向通信を可能にする技術で、特にリアルタイム通信を必要とするアプリケーションで用いられます。

例えば、チャットアプリやオンラインゲームなどがこれに該当します。

C++でWebSocket通信を実装する際には、専用のライブラリを使用することが一般的です。

これらのライブラリは、WebSocketプロトコルの複雑な部分を抽象化し、開発者がより簡単に通信機能を組み込むことを助けます。

WebSocket通信を行う基本的なプロセスは以下の通りです。

まず、クライアント(通常はウェブブラウザ)がサーバに対してWebSocket接続を要求します。

この要求は、HTTPプロトコルを使用して行われ、サーバがこの要求を受け入れると、接続はWebSocketプロトコルに「アップグレード」されます。

接続が確立されると、クライアントとサーバ間でメッセージがリアルタイムに交換されるようになります。

○サンプルコード1:簡単なエコーサーバの作成

次に、WebSocket通信の基本的な使い方を示すために、C++で簡単なエコーサーバを作成するサンプルコードを紹介します。

エコーサーバは、クライアントから受け取ったメッセージをそのままクライアントに返送する単純なサーバです。

このサンプルコードでは、C++のWebSocketライブラリを使用しています。

#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

typedef websocketpp::server<websocketpp::config::asio> server;

void on_message(server* s, websocketpp::connection_hdl hdl, server::message_ptr msg) {
    try {
        s->send(hdl, msg->get_payload(), msg->get_opcode());
    } catch (websocketpp::exception const & e) {
        std::cout << "Echo failed because: " << e.what() << std::endl;
    }
}

int main() {
    server echo_server;

    try {
        echo_server.set_access_channels(websocketpp::log::alevel::all);
        echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);

        echo_server.init_asio();
        echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
        echo_server.listen(9002);
        echo_server.start_accept();

        echo_server.run();
    } catch (websocketpp::exception const & e) {
        std::cout << "Failed to run server because: " << e.what() << std::endl;
    }
}

このコードは、ポート9002でWebSocketサーバを起動し、クライアントからのメッセージを待ち受けます。

クライアントからメッセージが送られてくると、on_message関数が呼び出され、受け取ったメッセージをそのままクライアントに返送します。

ここで使用されているwebsocketppは、C++用のWebSocketライブラリの一つであり、非常に柔軟かつ強力な機能を提供します。

○サンプルコード2:クライアントからのメッセージ送信

最後に、WebSocket通信のもう一つの重要な側面である、クライアントからサーバへのメッセージ送信を行うサンプルコードを紹介します。

この例では、簡単なWebSocketクライアントを作成し、サーバにメッセージを送信する方法を説明します。

#include <iostream>
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>

typedef websocketpp::client<websocketpp::config::asio_client> client;

int main() {
    client c;
    std::string uri = "ws://localhost:9002";

    try {
        websocketpp::lib::error_code ec;
        client::connection_ptr con = c.get_connection(uri, ec);

        if (ec) {
            std::cout << "Could not create connection because: " << ec.message() << std::endl;
            return 0;
        }

        c.connect(con);

        c.run();
    } catch (websocketpp::exception const & e) {
        std::cout << "Failed to connect because: " << e.what() << std::endl;
    }
}

このコードでは、WebSocketクライアントを作成し、先ほど作成したエコーサーバ(ポート9002で動作中)に接続を試みます。

接続が成功すると、サーバにメッセージを送信できます。

このサンプルでは、実際のメッセージ送信の部分は省略していますが、実際のアプリケーションでは、sendメソッドを使用してサーバにデータを送信します。

●WebSocket通信の応用例

WebSocket通信技術は、そのリアルタイム性と効率的なデータ交換機能により、さまざまな応用分野で利用されています。

例えば、リアルタイムチャットアプリケーションやオンラインゲーム、金融市場のリアルタイムデータ配信など、WebSocketはこれらの分野で幅広く採用されている技術です。

また、IoTデバイスの制御やモニタリング、ライブストリーミングなどの用途でもWebSocket通信が活用されています。

このようにWebSocketは、インタラクティブなウェブアプリケーションやリアルタイムデータのやり取りを必要とするあらゆる分野でその能力を発揮しています。

○サンプルコード3:リアルタイムチャットアプリケーション

このサンプルコードでは、C++を使用してリアルタイムのチャットアプリケーションを作成する方法を表しています。

このアプリケーションでは、WebSocketサーバーが複数のクライアントからの接続を受け入れ、送信されたメッセージを他の全てのクライアントにブロードキャストします。

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

typedef websocketpp::server<websocketpp::config::asio> server;

using websocketpp::connection_hdl;
using namespace std;

class chat_server {
public:
    chat_server() {
        m_server.init_asio();

        m_server.set_open_handler(bind(&chat_server::on_open, this, ::_1));
        m_server.set_close_handler(bind(&chat_server::on_close, this, ::_1));
        m_server.set_message_handler(bind(&chat_server::on_message, this, ::_1, ::_2));
    }

    void on_open(connection_hdl hdl) {
        m_connections.insert(hdl);
    }

    void on_close(connection_hdl hdl) {
        m_connections.erase(hdl);
    }

    void on_message(connection_hdl hdl, server::message_ptr msg) {
        for (auto it : m_connections) {
            m_server.send(it, msg->get_payload(), msg->get_opcode());
        }
    }

    void run(uint16_t port) {
        m_server.listen(port);
        m_server.start_accept();
        m_server.run();
    }

private:
    server m_server;
    set<connection_hdl, std::owner_less<connection_hdl>> m_connections;
};

int main() {
    chat_server server;
    server.run(9002);
}

このコードは、WebSocketサーバーを初期化し、接続、切断、メッセージ受信時のイベントハンドラーを設定します。

on_open関数は新しい接続が確立された時に呼び出され、on_close関数は接続が閉じられた時に呼び出されます。

on_message関数は、クライアントからメッセージを受け取った際に、そのメッセージを全ての接続されているクライアントにブロードキャストします。

run関数はサーバーを起動し、指定されたポートでリッスンします。この例では、ポート9002でサーバーが起動します。

このサンプルコードを実行すると、WebSocketサーバーが起動し、クライアントからの接続を待機します。

クライアントは、このサーバーに接続し、メッセージを送信できます。

サーバーは受信したメッセージを全ての接続済みクライアントにブロードキャストし、リアルタイムでのコミュニケーションを可能にします。

○サンプルコード4:マルチスレッドによる通信の管理

次に、C++でのWebSocket通信において、マルチスレッドを使用して通信の管理を行う方法を示します。

このサンプルコードでは、複数のクライアントからの同時接続を効率的に処理するために、マルチスレッドを活用しています。

// WebSocketサーバーの基本設定はサンプルコード3と同様です。

void chat_server::run(uint16_t port) {
    m_server.listen(port);
    m_server.start_accept();

    // マルチスレッドでサーバーを実行
    std::vector<std::thread> threads;
    for (int i = 0; i < 4; ++i) {
        threads.push_back(std::thread([&]() {
            m_server.run();
        }));
    }

    for (auto &t : threads) {
        t.join();
    }
}

int main() {
    chat_server server;
    server.run(9002);
}

このサンプルコードでは、run関数内で複数のスレッドを生成し、各スレッドでm_server.run()を呼び出しています。

これにより、サーバーは複数のスレッド上で並行して実行され、複数のクライアントからの接続を同時に処理することが可能になります。

この方法は、特に多くのクライアントが同時に接続するような場合に効果的です。

○サンプルコード5:セキュアな通信の実装

最後に、C++でWebSocket通信においてセキュリティを強化する方法を紹介します。

セキュリティは、特に公開されたウェブアプリケーションにおいて重要な要素です。

このサンプルコードでは、SSL/TLSを使用して暗号化されたWebSocket通信を行っています。

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

// その他の基本設定はサンプルコード3, 4と同様です。

void chat_server::run(uint16_t port) {
    // SSLコンテキストの設定
    m_server.set_tls_init_handler([](websocketpp::connection_hdl) {
        return websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv12);
    });

    m_server.listen(port);
    m_server.start_accept();

    m_server.run();
}

int main() {
    chat_server server;
    server.run(9002);
}

このサンプルコードでは、set_tls_init_handler関数を使用して、SSL/TLSコンテキストを設定しています。

これにより、サーバーはSSL/TLSを使用してクライアントとの通信を暗号化し、セキュリティを向上させます。

TLS(Transport Layer Security)は、データのプライバシーとデータの完全性を保護するためのプロトコルであり、WebSocket通信においても重要な役割を果たします。

●注意点と対処法

WebSocket通信を利用する際には、いくつかの重要な注意点があります。

まず、WebSocketはTCP/IPプロトコルに基づいて動作するため、ネットワークの安定性が重要です。

不安定なネットワーク環境では、接続が頻繁に切断される可能性があります。

そのため、WebSocketサーバーを設置する際は、信頼性の高いネットワーク環境を選ぶことが肝心です。

また、WebSocket通信はリアルタイム性が求められることが多く、高速なデータのやり取りが必要になる場面があります。

このため、サーバーの処理能力や帯域幅も重要な要素となります。

適切なリソース配分と、必要に応じたスケーリング計画を立てることが、効率的なWebSocket通信の実現につながります。

セキュリティ面では、WebSocketはその性質上、外部からの攻撃に対して脆弱な側面を持っています。

例えば、Cross-Site WebSocket Hijacking (CSWSH) 攻撃では、攻撃者がユーザーのブラウザを介してWebSocket接続を乗っ取ることが可能です。

これを防ぐためには、WebSocket通信にセキュリティトークンを使用することが推奨されます。

セキュリティトークンを利用することで、不正な接続を効果的にブロックできます。

○接続の安定性を保つためのポイント

WebSocket通信の接続安定性を高めるためには、いくつかの技術的な対策が有効です。

例えば、Heartbeatメッセージの定期的な送信は、接続が活性であることを確認し、不必要なタイムアウトを防ぐのに役立ちます。

また、通信路の品質を定期的に監視し、品質の低下が見られた場合は速やかに再接続を試みるなどの対策も有効です。

さらに、WebSocketサーバーのスケーラビリティにも注意を払う必要があります。

サーバーが多数の同時接続を処理できるように、適切なリソースの割り当てと負荷分散の仕組みを導入することが重要です。

これにより、大量のユーザーが同時に接続してもサービスの品質を維持することが可能になります。

○セキュリティ上の注意点

WebSocketを使用する際のセキュリティ面での最も重要な点は、暗号化された通信路の使用です。

WebSocket通信では、ws://ではなく、wss://(WebSocket Secure)プロトコルを使用することで、通信内容が暗号化され、第三者によるデータの傍受や改ざんを防ぐことができます。

また、WebSocket APIを使用する際は、Cross-Origin Resource Sharing (CORS) ポリシーに注意する必要があります。

CORS設定を適切に行うことで、不正なオリジンからのリクエストを防ぎ、セキュリティを向上させることができます。

さらに、WebSocket通信を使用するアプリケーションでは、入力データのバリデーションを徹底することが必要です。

特に、SQLインジェクションやクロスサイトスクリプティング(XSS)などの攻撃に対して、サニタイズやエスケープ処理を行うことで、アプリケーションのセキュリティを強化することができます。

●C++でのWebSocket通信のカスタマイズ方法

WebSocket通信をC++で実装する際、カスタマイズすることでさまざまな応用が可能になります。

特に、プロトコルの拡張やパフォーマンスの最適化は、WebSocket通信の有効性を高めるために重要な要素です。

WebSocket通信のカスタマイズを行うことで、アプリケーションの特定の要件に合わせて通信プロセスを調整し、より効率的で安定した通信を実現することができます。

○プロトコル拡張の実装

WebSocketプロトコルは基本的にはテキストやバイナリデータのやり取りをサポートしていますが、特定のアプリケーションではこれらの基本的な機能に加えて、独自の拡張が必要になることがあります。

例えば、カスタムヘッダーの追加や特定のデータ形式の使用などが考えられます。

C++でWebSocket通信をカスタマイズする際には、使用しているライブラリが拡張機能をサポートしているかを確認し、必要に応じて独自のプロトコル拡張を実装します。

// WebSocket++ライブラリを使用したプロトコル拡張の例
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

typedef websocketpp::server<websocketpp::config::asio> server;

void on_message(server* s, websocketpp::connection_hdl hdl, server::message_ptr msg) {
    // カスタムヘッダーや特定のデータ形式を処理するロジックをここに実装
}

int main() {
    server echo_server;

    // サーバー設定などの基本的な処理は同じ
    echo_server.init_asio();
    echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));

    echo_server.run();
}

この例では、独自のロジックを追加してWebSocketプロトコルを拡張しています。

このようにして、アプリケーション特有の要件に合わせた通信機能を実装することが可能です。

○パフォーマンスの最適化

WebSocket通信のパフォーマンスを最適化することは、特にリアルタイム性が求められるアプリケーションにおいて重要です。

パフォーマンスの最適化には、サーバーのリソース管理、通信プロトコルの効率化、ネットワークの遅延の最小化などが含まれます。

C++におけるパフォーマンスの最適化では、マルチスレッディングの利用、非同期I/Oの採用、メモリ管理の最適化などが考えられます。

// 非同期I/Oとマルチスレッディングを利用したパフォーマンス最適化の例
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <thread>

typedef websocketpp::server<websocketpp::config::asio> server;

void run_server(server* s) {
    s->run();
}

int main() {
    server echo_server;
    echo_server.init_asio();

    // マルチスレッドでサーバーを実行
    std::thread thread1(run_server, &echo_server);
    std::thread thread2(run_server, &echo_server);

    thread1.join();
    thread2.join();
}

この例では、マルチスレッドを利用してサーバーの処理能力を向上させ、非同期I/Oによりリソースの利用効率を高めています。

まとめ

この記事では、C++を用いたWebSocket通信の基礎から応用までを幅広くカバーしました。

初心者には理解しやすい基本的な概念の説明から始まり、サンプルコードを通じて具体的な実装方法を紹介しました。

これにより、C++でのWebSocket通信の設定、基本的な使い方、さらには応用例までを学ぶことができます。

また、接続の安定性やセキュリティに関する注意点、WebSocket通信のカスタマイズ方法についても詳細に解説しました。

この知識を活用することで、C++を用いたWebSocket通信のプログラミングがより深く理解できるでしょう。