【通信抽象化(Communication)】
はじめに(CUEI の “C” が示す通信抽象化の指針)
通信抽象化の位置づけ(CUEI の C が求めるもの)
CUEI アーキテクチャの “C(Communication)” は、通信方式の多様化に耐え、サーバー(サービス)コンテンツと疎結合な通信基盤を構築するための設計指針 を示します。
この指針は技法を縛るものではなく、
「どのような実装方式であっても、通信方式の差異に依存しない抽象化を実現できること」
を要件としています。
CUEI はあくまで アーキテクチャ思想 であり、
ステートマシンや UNIT/Queue モデルといった具体的な技法を要求するものではありません。
SOCKET-MANAGER Framework における実装方針
SOCKET-MANAGER Framework では、この CUEI の指針を実現するために、プロトコル部(通信仕様を扱うビジネスロジック) と
コマンド部(サーバー/サービスコンテンツとしてのビジネスロジック) を完全に分離する技法を採用しています。
プロトコル部は TCP / UDP / WebSocket / IPC / 独自プロトコルなど多様な通信方式を抽象化し、
コマンド部はサービス固有の処理を担当します。
この二層構造は CUEI が必須とするものではありませんが、
通信方式の多様化への耐性と、サーバーコンテンツとの疎結合という CUEI の要件に極めて忠実な実装方式 です。
本ページで扱う内容
本ページでは、SOCKET-MANAGER Framework が CUEI の “Communication” をどのように実現しているかを、以下の技法を中心に解説します。・ステートマシン型通信モデル
・プロトコル部とコマンド部の二層構造
・UNIT / Queue モデルによる状態遷移の表現
・多様なプロトコル(TCP / UDP / WebSocket / IPC / 独自プロトコル)への対応方法
これらは CUEI の必須要件ではなく、CUEI の指針を忠実に実現するための SOCKET-MANAGER Framework 独自の技法 です。
通信抽象化とは(SOCKET-MANAGER Framework における実装)
本セクションでは、SOCKET-MANAGER Framework が CUEI の通信抽象化をどのように実装しているかを解説します。
ここで扱う内容は CUEI の必須要件ではなく、SOCKET-MANAGER Framework が採用する具体的な技法 です。
本フレームワークにおける通信抽象化は、TCP(RFC 793)・ UDP(RFC 768)・ WebSocket(RFC 6455)・IPC などの 異なる通信方式を、単一の構造と同じ思想で扱えるようにするための設計モデルです。
HTTP のような「リクエスト/レスポンス前提」のモデルとは異なり、 ソケット通信は 接続維持を前提とした連続的な状態遷移 を伴います。
そのため、単発のイベントハンドラだけで通信を捉えるのではなく、 「どのタイミング(イベントの起点)をきっかけに、どのようなステート処理が連なっていくか」を 明確に設計する必要があります。
一般的なイベント駆動型フレームワークは イベントループ 上でハンドラを実行する構造が主流ですが、本フレームワークでは イベントの起点とステート処理をステートマシンとして構造化し、 さらにそれを UNIT / Queue モデルとしてフレームワーク側にビルトインしている点が大きく異なります。
この構造の違いが、「プロトコルそのものを自作できるレベルの柔軟性」と 「壊れにくいリアルタイム処理」の両立につながっています。
このページでは、本フレームワークが採用する ステートマシン型の通信モデルを中心に、 プロトコル部とコマンド部の二層構造による通信抽象化の仕組みを解説します。
UNIT / Queue / Module の三層構造そのものについては、 >> アーキテクチャ(キューとUNITの関係) や >> イベント駆動アーキテクチャ を参照してください。
ここで扱う内容は CUEI の必須要件ではなく、SOCKET-MANAGER Framework が採用する具体的な技法 です。
本フレームワークにおける通信抽象化は、TCP(RFC 793)・ UDP(RFC 768)・ WebSocket(RFC 6455)・IPC などの 異なる通信方式を、単一の構造と同じ思想で扱えるようにするための設計モデルです。
HTTP のような「リクエスト/レスポンス前提」のモデルとは異なり、 ソケット通信は 接続維持を前提とした連続的な状態遷移 を伴います。
そのため、単発のイベントハンドラだけで通信を捉えるのではなく、 「どのタイミング(イベントの起点)をきっかけに、どのようなステート処理が連なっていくか」を 明確に設計する必要があります。
一般的なイベント駆動型フレームワークは イベントループ 上でハンドラを実行する構造が主流ですが、本フレームワークでは イベントの起点とステート処理をステートマシンとして構造化し、 さらにそれを UNIT / Queue モデルとしてフレームワーク側にビルトインしている点が大きく異なります。
この構造の違いが、「プロトコルそのものを自作できるレベルの柔軟性」と 「壊れにくいリアルタイム処理」の両立につながっています。
このページでは、本フレームワークが採用する ステートマシン型の通信モデルを中心に、 プロトコル部とコマンド部の二層構造による通信抽象化の仕組みを解説します。
UNIT / Queue / Module の三層構造そのものについては、 >> アーキテクチャ(キューとUNITの関係) や >> イベント駆動アーキテクチャ を参照してください。
ステートマシン型通信(プロトコル部の起点)
ここで説明するステートマシンは、プロトコル部に属するものです。
つまり、TCP / UDP / WebSocket / IPC といった 「通信プロトコルそのものの振る舞い」を表現するための枠組みです。
ステートマシン(有限状態機械) という概念をプロトコル処理に適用することで、 通信の振る舞いを構造化し、状態遷移を明確に定義できます。
プロトコル部では、通信処理の開始点となるイベントを 次の 5 つの 起点 として定義します。
これらは単なる「イベント名」ではなく、 状態遷移の起点としてのラベルです。
各起点ごとに「どのような入力を受け取り、どのようなステート処理を行い、どの状態へ遷移するか」を ステートマシンとして書き出していくことで、 プロトコル全体の振る舞いを構造的に整理できます。
本フレームワークの UNIT / Queue モデルに対応付けると、
これら 5 つの起点がそれぞれ 1 つの Queue(キュー)に相当し、 その中に並ぶ個々のステート処理が UNIT(ステータスUNIT)に相当します。
例えば WebSocket の「Upgrade リクエスト受信」⇒「Upgrade 許可レスポンス送信」という流れは、 ACCEPT 起点(ACCEPT キュー)の中に連結された複数の UNIT として表現されます。
このとき重要なのは、この 5 つの起点はあくまでプロトコル部専用の枠組みであり、 後述するコマンド部でも同じ 5 つを使う必要はない、という点です。
コマンド部では、アプリケーションのビジネスロジックに応じて 自由な起点名(ENTRANCE / MESSAGE など)を定義できます。
また、この起点構造は WebSocket や TCP/UDP だけでなく、 独自プロトコル実装(プロトコル自作)にもそのまま適用できます。
フレーム構造・ハンドシェイク・状態遷移を自由に定義し、 通信仕様そのものを設計できる抽象化レイヤーとして利用できます。
そして、起点ごとにステートマシンを設計しておくことで、 そのまま 状態遷移図として活用できる点も重要です。
これは単なる技術的メリットに留まらず、 ITIL v4 が重視する “価値中心・継続的改善” の観点でも 改善ポイントの可視化や変更管理に役立ちます。
ITIL との関係については >> 技術版 ITIL としての CUEI/O を参照してください。
つまり、TCP / UDP / WebSocket / IPC といった 「通信プロトコルそのものの振る舞い」を表現するための枠組みです。
ステートマシン(有限状態機械) という概念をプロトコル処理に適用することで、 通信の振る舞いを構造化し、状態遷移を明確に定義できます。
プロトコル部では、通信処理の開始点となるイベントを 次の 5 つの 起点 として定義します。
- ACCEPT / CONNECT:接続時のハンドシェイクの起点
- RECV:データ受信の起点
- SEND:データ送信の起点
- ALIVE:アライブチェックの起点
- CLOSE:切断処理の起点
これらは単なる「イベント名」ではなく、 状態遷移の起点としてのラベルです。
各起点ごとに「どのような入力を受け取り、どのようなステート処理を行い、どの状態へ遷移するか」を ステートマシンとして書き出していくことで、 プロトコル全体の振る舞いを構造的に整理できます。
本フレームワークの UNIT / Queue モデルに対応付けると、
これら 5 つの起点がそれぞれ 1 つの Queue(キュー)に相当し、 その中に並ぶ個々のステート処理が UNIT(ステータスUNIT)に相当します。
例えば WebSocket の「Upgrade リクエスト受信」⇒「Upgrade 許可レスポンス送信」という流れは、 ACCEPT 起点(ACCEPT キュー)の中に連結された複数の UNIT として表現されます。
このとき重要なのは、この 5 つの起点はあくまでプロトコル部専用の枠組みであり、 後述するコマンド部でも同じ 5 つを使う必要はない、という点です。
コマンド部では、アプリケーションのビジネスロジックに応じて 自由な起点名(ENTRANCE / MESSAGE など)を定義できます。
また、この起点構造は WebSocket や TCP/UDP だけでなく、 独自プロトコル実装(プロトコル自作)にもそのまま適用できます。
フレーム構造・ハンドシェイク・状態遷移を自由に定義し、 通信仕様そのものを設計できる抽象化レイヤーとして利用できます。
そして、起点ごとにステートマシンを設計しておくことで、 そのまま 状態遷移図として活用できる点も重要です。
これは単なる技術的メリットに留まらず、 ITIL v4 が重視する “価値中心・継続的改善” の観点でも 改善ポイントの可視化や変更管理に役立ちます。
ITIL との関係については >> 技術版 ITIL としての CUEI/O を参照してください。
プロトコル部の構造(WebSocket の例)
プロトコル部は、標準プロトコルだけでなく
独自プロトコル実装やプロトコルレベルの拡張にも対応しています。
いわゆる「シリアライズ形式を変えるだけのカスタムプロトコル」ではなく、 フレーム構造・ハンドシェイク・状態遷移を含めた 通信仕様そのものを自由に設計できる点が特徴です。
なお、ブラウザ側の WebSocket API 仕様については >> W3C WebSocket API も参考になります。
以下は WebSocket サーバーを例にした主要な起点の流れです。
ACCEPT 起点(接続時のハンドシェイク)
Upgrade リクエスト受信 ⇒ Upgrade 許可レスポンス送信
RECV 起点(データ受信)
フレームヘッダ受信 ⇒ ヘッダ解析 ⇒ ペイロード抽出
SEND 起点(データ送信)
フレームヘッダ生成 ⇒ ペイロードを含めたデータ送信
ALIVE 起点(アライブチェック)
ping フレーム生成 ⇒ ping 送信 ⇒ pong 受信
CLOSE 起点(切断処理)
close フレーム生成 ⇒ close フレーム送信
これらの起点ごとに処理の流れを整理しておくことで、 WebSocket の振る舞いを 事前に設計可能な状態遷移図として扱えます。
実装はこの設計図に沿って行うだけになるため、 プロトコル仕様の抜け漏れや解釈のズレを減らしやすくなります。
なお、プロトコル部のステートマシンの中身は フレームワークが固定するものではなく、 どの起点でどのような処理を行うかはデベロッパーが自由に構築できます。
例えば、ACCEPT 起点の中で認証ロジックを組み込む、といった構成も可能です。
これらのステート処理は、内部的には ProtocolQueueEnum で表現される各キューにぶら下がる UNIT 群として実装されます。
具体的な UNIT 定義クラスや Enum の構成については、 >> アーキテクチャ(UNIT定義クラス) を参照してください。
いわゆる「シリアライズ形式を変えるだけのカスタムプロトコル」ではなく、 フレーム構造・ハンドシェイク・状態遷移を含めた 通信仕様そのものを自由に設計できる点が特徴です。
なお、ブラウザ側の WebSocket API 仕様については >> W3C WebSocket API も参考になります。
以下は WebSocket サーバーを例にした主要な起点の流れです。
ACCEPT 起点(接続時のハンドシェイク)
Upgrade リクエスト受信 ⇒ Upgrade 許可レスポンス送信
RECV 起点(データ受信)
フレームヘッダ受信 ⇒ ヘッダ解析 ⇒ ペイロード抽出
SEND 起点(データ送信)
フレームヘッダ生成 ⇒ ペイロードを含めたデータ送信
ALIVE 起点(アライブチェック)
ping フレーム生成 ⇒ ping 送信 ⇒ pong 受信
CLOSE 起点(切断処理)
close フレーム生成 ⇒ close フレーム送信
これらの起点ごとに処理の流れを整理しておくことで、 WebSocket の振る舞いを 事前に設計可能な状態遷移図として扱えます。
実装はこの設計図に沿って行うだけになるため、 プロトコル仕様の抜け漏れや解釈のズレを減らしやすくなります。
なお、プロトコル部のステートマシンの中身は フレームワークが固定するものではなく、 どの起点でどのような処理を行うかはデベロッパーが自由に構築できます。
例えば、ACCEPT 起点の中で認証ロジックを組み込む、といった構成も可能です。
これらのステート処理は、内部的には ProtocolQueueEnum で表現される各キューにぶら下がる UNIT 群として実装されます。
具体的な UNIT 定義クラスや Enum の構成については、 >> アーキテクチャ(UNIT定義クラス) を参照してください。
コマンド部の構造(チャットサーバーの例)
コマンド部は、アプリケーションのビジネスロジックを
ステートマシンとして構築する層です。
「コマンド部」という名称は、この層で扱うキューが コマンドUNIT(コマンドを表現する UNIT 群)として設計されていることに由来します。
1 つのコマンド(入室、メッセージ送信、退室など)を 1 本の Queue として捉え、 その中に複数の UNIT(検証・検索・配信・ログ記録など)を連ねていくイメージです。
プロトコル部と同じ UNIT / Queue モデルの上に乗りながらも、 「何をコマンドとみなすか」はアプリケーション側で自由に設計できます。
以下は WebSocket を利用したチャットサーバーを例にしたコマンド部の起点です。
ENTRANCE(入室処理)
ユーザー名の抽出 ⇒ 部屋へのエントリ ⇒ 入室メッセージ配信
MESSAGE(通常メッセージ)
同室メンバーへのメッセージ配信
PRIVATE_MESSAGE(宛先指定メッセージ)
宛先ユーザーの部屋特定 ⇒ 宛先ユーザーへのメッセージ配信
CLOSE_REQUEST(切断要求)
同室ユーザーへの退室メッセージ配信 ⇒ 切断フレームのレスポンス送信
ここでも、各起点から始まる一連の処理は ステートマシンとして整理できます。
これを UNIT / Queue の内部モデルに対応付けると、
ENTRANCE / MESSAGE / PRIVATE_MESSAGE / CLOSE_REQUEST といった起点が それぞれ 1 つの Queue(コマンドキュー)に相当し、 その中に並ぶステート処理がコマンドUNITとして実装される形になります。
プロトコル部と同じ思想でありながら、 起点名や処理内容はビジネスロジックに最適化された形で 自由に設計できる点が特徴です。
コマンドUNIT の具体的な設計パターン(再利用UNIT・ポーリングUNIT・リトライUNITなど)については、 >> イベントハンドラについて を参照してください。
「コマンド部」という名称は、この層で扱うキューが コマンドUNIT(コマンドを表現する UNIT 群)として設計されていることに由来します。
1 つのコマンド(入室、メッセージ送信、退室など)を 1 本の Queue として捉え、 その中に複数の UNIT(検証・検索・配信・ログ記録など)を連ねていくイメージです。
プロトコル部と同じ UNIT / Queue モデルの上に乗りながらも、 「何をコマンドとみなすか」はアプリケーション側で自由に設計できます。
以下は WebSocket を利用したチャットサーバーを例にしたコマンド部の起点です。
ENTRANCE(入室処理)
ユーザー名の抽出 ⇒ 部屋へのエントリ ⇒ 入室メッセージ配信
MESSAGE(通常メッセージ)
同室メンバーへのメッセージ配信
PRIVATE_MESSAGE(宛先指定メッセージ)
宛先ユーザーの部屋特定 ⇒ 宛先ユーザーへのメッセージ配信
CLOSE_REQUEST(切断要求)
同室ユーザーへの退室メッセージ配信 ⇒ 切断フレームのレスポンス送信
ここでも、各起点から始まる一連の処理は ステートマシンとして整理できます。
これを UNIT / Queue の内部モデルに対応付けると、
ENTRANCE / MESSAGE / PRIVATE_MESSAGE / CLOSE_REQUEST といった起点が それぞれ 1 つの Queue(コマンドキュー)に相当し、 その中に並ぶステート処理がコマンドUNITとして実装される形になります。
プロトコル部と同じ思想でありながら、 起点名や処理内容はビジネスロジックに最適化された形で 自由に設計できる点が特徴です。
コマンドUNIT の具体的な設計パターン(再利用UNIT・ポーリングUNIT・リトライUNITなど)については、 >> イベントハンドラについて を参照してください。
コマンドディスパッチャー(プロトコル部とコマンド部の橋渡し)
プロトコル部とコマンド部をつなぐのが
コマンドディスパッチャーです。
コマンドディスパッチャーは、プロトコル部の RECV 起点で受信したデータを解析し、 内容に応じてコマンド部の起点(ENTRANCE / MESSAGE など)を発行します。
場合によっては、ACCEPT 起点で受信した内容(例:初回の認証情報や Upgrade リクエスト)を 解析対象とすることもできます。
ここで重要なのは、このアーキテクチャでは プロトコル部もコマンド部も、どちらもビジネスロジックであるという点です。
プロトコル部は「通信仕様としてのビジネスロジック」を、 コマンド部は「アプリケーションとしてのビジネスロジック」を担います。
コマンドディスパッチャーは、その 2 つのビジネスロジックを 疎結合に橋渡しする役割を持っています。
そのため、この構造を言い換えると、
「プロトコル部とコマンド部のビジネスロジックを完全に分離したまま、 データの流れだけを自然に接続できる」アーキテクチャになっていると言えます。
プロトコルを差し替えてもコマンド部はそのまま動作させることができ、 コマンド部を差し替えてもプロトコル部の実装はそのまま再利用できます。
詳細な構造やフローについては、 >> アーキテクチャ(レイヤー概念図) ページで図解しています。
コマンドディスパッチャーは、プロトコル部の RECV 起点で受信したデータを解析し、 内容に応じてコマンド部の起点(ENTRANCE / MESSAGE など)を発行します。
場合によっては、ACCEPT 起点で受信した内容(例:初回の認証情報や Upgrade リクエスト)を 解析対象とすることもできます。
ここで重要なのは、このアーキテクチャでは プロトコル部もコマンド部も、どちらもビジネスロジックであるという点です。
プロトコル部は「通信仕様としてのビジネスロジック」を、 コマンド部は「アプリケーションとしてのビジネスロジック」を担います。
コマンドディスパッチャーは、その 2 つのビジネスロジックを 疎結合に橋渡しする役割を持っています。
そのため、この構造を言い換えると、
「プロトコル部とコマンド部のビジネスロジックを完全に分離したまま、 データの流れだけを自然に接続できる」アーキテクチャになっていると言えます。
プロトコルを差し替えてもコマンド部はそのまま動作させることができ、 コマンド部を差し替えてもプロトコル部の実装はそのまま再利用できます。
詳細な構造やフローについては、 >> アーキテクチャ(レイヤー概念図) ページで図解しています。
抽象化の全体像(プロトコル部+コマンド部+UNIT/Queue)
本フレームワークにおける通信抽象化は、TCP / UDP / WebSocket / IPC に加えて、
独自プロトコル実装やプロトコルレベルの拡張にも対応しています。
プロトコル部の起点構造が共通化されているため、 任意の通信仕様をステートマシンとして自由に設計できます。
次の三層構造によって、プロトコル差異を吸収しつつ ビジネスロジックを柔軟に構築できます。
フレームワークが提供するのは、この三層構造の枠組みです。
その中で「どの起点で何を行うか」「どのような状態遷移を設計するか」は、 すべてデベロッパーが自由に構築できます。
また、この三層構造は >> イベント駆動アーキテクチャ(抽象化されたステートマシン) で解説している CycleDrivenManager の上に実装されています。
一般的なイベント駆動型とは異なり、イベントループそのものがステートマシン(UNIT / Queue)として動作するため、 プロトコル部・コマンド部・IPC モジュールなどを同一モデルで安全に共存させることができます。
このモデルにより、プロトコルの違いに縛られず、 ビジネスロジックに集中したサーバー設計が可能になります。
プロトコル部の起点構造が共通化されているため、 任意の通信仕様をステートマシンとして自由に設計できます。
次の三層構造によって、プロトコル差異を吸収しつつ ビジネスロジックを柔軟に構築できます。
- プロトコル部
— ACCEPT / RECV / SEND / ALIVE / CLOSE の起点を持つ通信ステートマシン。
— 各起点は ProtocolQueueEnum による Queue として表現され、その中のステート処理が UNIT として実装される。 - コマンドディスパッチャー
— プロトコル部で受信した内容を解析し、コマンド部の起点へ橋渡しする。
— プロトコル部とコマンド部のビジネスロジックを疎結合に保つ。 - コマンド部
— ENTRANCE / MESSAGE など、ビジネスロジックに応じた起点を持つステートマシン。
— 各起点はコマンドキューとして表現され、その中のステート処理がコマンドUNITとして実装される。
フレームワークが提供するのは、この三層構造の枠組みです。
その中で「どの起点で何を行うか」「どのような状態遷移を設計するか」は、 すべてデベロッパーが自由に構築できます。
また、この三層構造は >> イベント駆動アーキテクチャ(抽象化されたステートマシン) で解説している CycleDrivenManager の上に実装されています。
一般的なイベント駆動型とは異なり、イベントループそのものがステートマシン(UNIT / Queue)として動作するため、 プロトコル部・コマンド部・IPC モジュールなどを同一モデルで安全に共存させることができます。
このモデルにより、プロトコルの違いに縛られず、 ビジネスロジックに集中したサーバー設計が可能になります。
まとめ(設計指針)
- ソケット通信は「接続維持+状態遷移」を前提としたモデルで捉える。
- プロトコル部では、ACCEPT / RECV / SEND / ALIVE / CLOSE の起点を軸にステートマシンを設計する。
- 各起点は Queue(キュー)として扱い、その中のステート処理を UNIT として構成する。
- プロトコルそのものを自作できるレベルの柔軟性を持ち、独自プロトコル実装にも対応する。
- コマンド部では、ビジネスロジックに応じた自由な起点名でステートマシンを構築できる。
- コマンドディスパッチャーが、プロトコル部とコマンド部のビジネスロジックを疎結合に橋渡しする。
- UNIT / Queue / Module の三層構造により、一般的なイベント駆動型とは異なる堅牢な状態管理モデルを実現する。
- 起点ごとのステートマシンは、そのまま状態遷移図として設計段階からITIL v4 的な継続的改善にも活用できる。
これらの設計指針により、CUEI は プロトコル非依存で拡張性の高い通信抽象化を実現します。
UNIT / Queue の実装寄りの視点から理解したい場合は >> イベントハンドラについて を、 フレームワーク全体のレイヤー構造から俯瞰したい場合は >> アーキテクチャ を併せてご覧ください。