blob: e42bf3dd2bd76706655ab4baf23a84738dcc0021 [file] [log] [blame] [view] [edit]
---
title: "WebSocket"
order: 8
---
cpp-httplibWebSocketにも対応しています。HTTPのリクエスト/レスポンスと違い、WebSocketはサーバーとクライアントが双方向にメッセージをやり取りできます。チャットやリアルタイム通知に便利です。
さっそく、エコーサーバーとクライアントを作ってみましょう。
## エコーサーバー
受け取ったメッセージをそのまま返すエコーサーバーです。
```cpp
#include "httplib.h"
#include <iostream>
int main() {
httplib::Server svr;
svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
std::string msg;
while (ws.read(msg)) {
ws.send(msg); // 受け取ったメッセージをそのまま返す
}
});
std::cout << "Listening on port 8080..." << std::endl;
svr.listen("0.0.0.0", 8080);
}
```
`svr.WebSocket()` WebSocketハンドラーを登録します。3章の `svr.Get()` `svr.Post()` と同じ感覚ですね。
ハンドラーの中では、`ws.read(msg)` でメッセージを待ちます。接続が閉じられると `read()` `false` を返すので、ループを抜けます。`ws.send(msg)` でメッセージを送り返します。
## クライアントからの接続
`httplib::ws::WebSocketClient` を使ってサーバーに接続してみましょう。
```cpp
#include "httplib.h"
#include <iostream>
int main() {
httplib::ws::WebSocketClient client("ws://localhost:8080/ws");
if (!client.connect()) {
std::cout << "Connection failed" << std::endl;
return 1;
}
// メッセージを送信
client.send("Hello, WebSocket!");
// サーバーからの応答を受信
std::string msg;
if (client.read(msg)) {
std::cout << msg << std::endl; // Hello, WebSocket!
}
client.close();
}
```
コンストラクタには `ws://host:port/path` 形式のURLを渡します。`connect()` で接続を開始し、`send()` `read()` でメッセージをやり取りします。
## テキストとバイナリ
WebSocketにはテキストとバイナリの2種類のメッセージがあります。`read()` の戻り値で区別できます。
```cpp
svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
std::string msg;
httplib::ws::ReadResult ret;
while ((ret = ws.read(msg))) {
if (ret == httplib::ws::Binary) {
ws.send(msg.data(), msg.size()); // バイナリとして送信
} else {
ws.send(msg); // テキストとして送信
}
}
});
```
- `ws.send(const std::string &)` テキストメッセージとして送信
- `ws.send(const char *, size_t)` バイナリメッセージとして送信
クライアント側も同じAPIです。
## リクエスト情報へのアクセス
ハンドラーの第1引数 `req` から、ハンドシェイク時のHTTPリクエスト情報を読み取れます。認証トークンの確認などに便利です。
```cpp
svr.WebSocket("/ws", [](const httplib::Request &req, httplib::ws::WebSocket &ws) {
auto token = req.get_header_value("Authorization");
if (token.empty()) {
ws.close(httplib::ws::CloseStatus::PolicyViolation, "unauthorized");
return;
}
std::string msg;
while (ws.read(msg)) {
ws.send(msg);
}
});
```
## WSSで使う
HTTPS上のWebSocketWSS)にも対応しています。サーバー側は `httplib::SSLServer` WebSocketハンドラーを登録するだけです。
```cpp
httplib::SSLServer svr("cert.pem", "key.pem");
svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
std::string msg;
while (ws.read(msg)) {
ws.send(msg);
}
});
svr.listen("0.0.0.0", 8443);
```
クライアント側は `wss://` スキームを使います。
```cpp
httplib::ws::WebSocketClient client("wss://localhost:8443/ws");
```
## 次のステップ
WebSocketの基本がわかりましたね。ここまでで Tourは終わりです。
次のページでは、Tourで取り上げなかった機能をまとめて紹介します。
**次:** [What's Next](../09-whats-next)