3.3 KiB
title, order, status
| title | order | status |
|---|---|---|
| E04. SSEをクライアントで受信する | 50 | draft |
cpp-httplibにはsse::SSEClientという専用のクラスが用意されています。自動再接続、イベント名別のハンドラ、Last-Event-IDの管理まで面倒を見てくれるので、SSEを受信するときはこれを使うのが一番ラクです。
基本の使い方
#include <httplib.h>
httplib::Client cli("http://localhost:8080");
httplib::sse::SSEClient sse(cli, "/events");
sse.on_message([](const httplib::sse::SSEMessage &msg) {
std::cout << "data: " << msg.data << std::endl;
});
sse.start(); // ブロッキング
Clientと接続先パスを渡してSSEClientを作り、on_message()でコールバックを登録します。start()を呼ぶとイベントループが走り、接続が切れると自動で再接続を試みます。
イベント名で分岐する
サーバー側でevent:を付けて送られてくる場合は、on_event()で名前ごとにハンドラを登録できます。
sse.on_event("message", [](const auto &msg) {
std::cout << "chat: " << msg.data << std::endl;
});
sse.on_event("join", [](const auto &msg) {
std::cout << msg.data << " joined" << std::endl;
});
sse.on_event("leave", [](const auto &msg) {
std::cout << msg.data << " left" << std::endl;
});
on_message()は、名前なし(デフォルトのmessageイベント)を受け取る汎用ハンドラとして使えます。
接続イベントとエラーハンドリング
sse.on_open([] {
std::cout << "connected" << std::endl;
});
sse.on_error([](httplib::Error err) {
std::cerr << "error: " << httplib::to_string(err) << std::endl;
});
接続確立時やエラー発生時にもフックを挟めます。エラーハンドラが呼ばれても、SSEClientは内部で再接続を試みます。
非同期で動かす
メインスレッドを塞ぎたくない場合はstart_async()を使います。
sse.start_async();
// メインスレッドは別の仕事を続ける
do_other_work();
// 終わったら止める
sse.stop();
start_async()は裏でスレッドを立ち上げてイベントループを回します。stop()でクリーンに止められます。
再接続の設定
再接続間隔や最大試行回数を調整できます。
sse.set_reconnect_interval(5000); // 5秒
sse.set_max_reconnect_attempts(10); // 10回まで(0=無制限)
サーバー側でretry:フィールドを送っていると、そちらが優先されます。
Last-Event-IDの自動管理
SSEClientは受信したイベントのidを内部で保持していて、再接続時にLast-Event-IDヘッダーとして送ってくれます。この挙動はサーバー側でid:付きイベントを送っていれば自動で有効になります。
std::cout << "last id: " << sse.last_event_id() << std::endl;
現在のIDはlast_event_id()で参照できます。
Note: SSEClientの
start()はブロッキングなので、単発のツールならそのまま使えますが、GUIアプリやサーバーに組み込むときはstart_async()+stop()の組み合わせが基本です。
サーバー側の実装はE01. SSEサーバーを実装するを参照してください。