kbmMWの次期バージョンでは、WebSocketプロトコルのネイティブサポートが追加される予定です。このアップデートにより、kbmMWのフレームワーク上でリアルタイム通信を行うWebサーバーを容易に構築できるようになります。
サーバーの実装は非常に直感的です。まず、TkbmMWServerとトランスポート層であるTkbmMWWebSocketServerTransportを初期化し、必要なイベントハンドラを関連付けます。
constructor TMainForm.Create(AOwner: TComponent);
begin
inherited;
// サーバーコンポーネントの生成
MWServer := TkbmMWServer.Create(nil);
// WebSocketトランスポートの生成と設定
WSTransport := TkbmMWWebSocketServerTransport.Create(nil);
WSTransport.Server := MWServer;
// イベントハンドラの割り当て
WSTransport.OnWebSocketData := ProcessIncomingData;
WSTransport.OnWebSocketOpen := HandleConnectionOpen;
WSTransport.OnWebSocketClose := HandleConnectionClose;
WSTransport.OnWebSocketPong := HandlePongResponse;
// サービスの自動登録
MWServer.AutoRegisterServices;
// ログ出力の設定
Logger.OutputToStrings(mmoLog.Lines);
end;
次に、サーバーの起動と停止、およびSSL/TLS通信の設定を行う処理を実装します。ここでは、SSLの有無によってポート番号や証明書のパスを動的に切り替えています。
procedure TMainForm.ToggleServerConnection(Sender: TObject);
begin
if MWServer.Active then
begin
MWServer.Active := False;
btnConnect.Caption := 'Start Server';
end
else
begin
WSTransport.Host := '0.0.0.0';
if chkUseSSL.Checked then
begin
// SSL設定
WSTransport.UseSSL := True;
WSTransport.Port := 443;
WSTransport.SetSSLCertificateFromFile('.\server.crt');
WSTransport.SetSSLPrivateKeyFromFile('.\server.key');
end
else
begin
// 非SSL設定
WSTransport.UseSSL := False;
WSTransport.Port := 8080;
end;
MWServer.Active := True;
btnConnect.Caption := 'Stop Server';
end;
end;
以下のコードは、WebSocket通信における各種イベント(接続確立、切断、メッセージ受信、Pong応答)の具体的な処理ロジックです。
procedure TMainForm.ProcessIncomingData(const AConnection: IkbmMWWebSocketConnection; const AData: TValue);
var
ReceivedText: string;
begin
ReceivedText := AData.ToString;
Logger.Info('Received data: ' + ReceivedText);
// 受信したデータを全クライアントにブロードキャスト
AConnection.BroadcastText(ReceivedText);
end;
procedure TMainForm.HandlePongResponse(const AConnection: IkbmMWWebSocketConnection; const AData: TValue);
begin
Logger.Info('Pong received from ' +
AConnection.GetPeerAddr + ':' + IntToStr(AConnection.GetPeerPort) +
' Data: ' + AData.ToString);
end;
procedure TMainForm.HandleConnectionOpen(const AConnection: IkbmMWWebSocketConnection);
begin
// 接続ごとに一意のタグを設定
AConnection.TagString := 'UserSession_' + IntToStr(GetTickCount);
Logger.Info('Connection opened: ' +
AConnection.GetPeerAddr + ':' + IntToStr(AConnection.GetPeerPort) +
' Tag: ' + AConnection.TagString);
end;
procedure TMainForm.HandleConnectionClose(const AConnection: IkbmMWWebSocketConnection; const ACode: Word; const AReason: string);
begin
Logger.Info('Connection closed: ' +
AConnection.GetPeerAddr + ':' + IntToStr(AConnection.GetPeerPort) +
' Code: ' + IntToStr(ACode) + ' Reason: ' + AReason);
end;
最後に、kbmMWウィザードを利用してSmart Web Serviceを作成し、HTTPリクエストをWebSocket接続にアップグレードするための処理を追加します。
unit uWebSocketService;
interface
uses
SysUtils, Classes, kbmMWSecurity, kbmMWServer, kbmMWServiceUtils,
kbmMWHTTPStdTransStream, kbmMWCustomHTTPSmartService, kbmMWRTTI;
type
[kbmMW_Service('flags:[listed]')]
[kbmMW_Rest('path:/')]
TWSGatewayService = class(TkbmMWCustomHTTPSmartService)
private
{ Private 宣言 }
protected
{ Protected 宣言 }
public
{ Public 宣言 }
[kbmMW_Rest('method:get, path:status')]
[kbmMW_Method]
function GetStatus: string;
// HTTPプロトコルをWebSocketにアップグレードするメソッド
function kbmMWCustomHTTPSmartServiceUpgrade(Sender: TObject;
const ARequestHelper, AResponseHelper: TkbmMWHTTPTransportStreamHelper;
const ARequestedProtocols: string;
var AAcceptedProtocol: string): Boolean;
end;
implementation
uses kbmMWExceptions;
function TWSGatewayService.GetStatus: string;
begin
Result := 'Service is running';
end;
function TWSGatewayService.kbmMWCustomHTTPSmartServiceUpgrade(Sender: TObject;
const ARequestHelper, AResponseHelper: TkbmMWHTTPTransportStreamHelper;
const ARequestedProtocols: string; var AAcceptedProtocol: string): Boolean;
begin
// プロトコルの受諾と設定
AAcceptedProtocol := 'websocket';
Result := True;
end;
initialization
TkbmMWRTTI.EnableRTTI(TWSGatewayService);
end.
以上で、kbmMWを使用したWebSocketサーバーの基本的な構築は完了です。