Boost.Beast で WebSocket を試す

Boost.Beast は Boost.Asio の上に実装された HTTP と WebSocket の C++ライブラリです。

WebSocket は 単一のTCPコネクション上に双方向通信のチャンネルを提供する 通信プロトコルです。 RFC 6455 として標準化されている。

Boost.Beast

wikipedia: WebSocket

RFC 6455 日本語訳

プロトコルの概要は下記が分かりやすかった。

mozilla: WebSocket サーバーの記述

qiita: WebSocketについて調べてみた

Boost の使い方は 下記を参考にした。

kyoto-u: Boostで通信

Github からサーバーとクライアントのサンプルコードを持ってきて、ビルドして実行する。

github: beast example websocket

すんなり動いた。

注意:
クライアントを実行すると下記のメッセージが出る。 Websocket.org は2021 年に閉鎖されたようだ。

Example websocket-client-sync echo.websocket.org 80 "Hello, world!"

Websocket.org Is Down

JvaScript クライアントからの接続も試す。

javascript: WebSocket

ソースを読んでみる。

websocket_client_sync.cpp の概要は下記のとおり。

websocket::stream<tcp::socket> ws{ioc};
ws.handshake(host, "/");
ws.write(net::buffer(std::string(text)));
ws.read(buffer);
ws.close(websocket::close_code::normal);

ほとんどの処理がライブラリを呼び出すだけ。

実行時にトレースメッセージは出ないので、 何をやっているか、分からず。

ライブラリのソースを読んでみる。 これは難解。

ソースを読むのは諦める。

TCP通信のやり取りを tcpdum で調べてみる。

qiita: 超絶初心者むけtcpdumpの使い方

% sudo tcpdump port 8080 -ilo0 -X

最初はオープニングハンドシェイク。 これは文字列の通信なのでわかりやすい。

client -> server
GET / HTTP/1.1
Host: localhost:8090
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Key: eDxQqF7QCZTWqNzVlz+3rA==
Sec-WebSocket-Version: 13
User-Agent: Boost.Beast/330 websocket-client-coro

server-> client
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: > NSiZPAhtEb04lODMOG24M7QH9So=
Server: Boost.Beast/330 websocket-server-sync

次に text(文字列) のエコーバック ここはバイナリなので、該当箇所を見つけるのに苦労する。

client -> server
818d b636 a1ed fe53 cd81 d91a 819a d944 cd89
server-> client
810d 4865 6c6c 6f2c 2077 6f72 6c64 21

最後にクロージングハンドシェイク。

client -> server
8882 673a 0f22 64d2
server-> client
8802 03e8

バイナリの解読が面倒だが、 プロトコルとおりであることが理解できた。

サンプルコードを Github に公開した https://github.com/ohwada/MAC_cpp_Samples/tree/master/boost_beast/websocket_sync