{{tag> projects:bbs_pm:manual}} ---json { "title":"ハンドラ", "description":"ハンドラ" } --- ====== ハンドラ ====== \\ ===== はじめに ===== BBS.pmはイベント駆動でノードが接続または切断するなど、システム内で発生するイベントに応じてハンドラが呼び出され、 ハンドラに設定されている処理を呼び出すことでアプリケーションサーバを操作します。\\ ここではハンドラについて説明します。\\ \\ ===== ハンドラ ===== 用意されているハンドラは次の通りです。\\
^ ハンドラ名 ^ 呼び出しの条件・目的 ^ | [[#onconnect|onConnect]] | 新たなノードが接続したとき | | [[#ondisconnect|onDisconnect]] | 接続中ノードが切断を試みたとき | | [[#onrecv|onRecv]] | onAccessイベントでノードからデータを受信したとき | | [[#onsend|onSend]] | 関数send()を呼び出したとき | | [[#output|Output]] | ノードに対してデータを送出する処理を行う | | [[#appwork|AppWork]] | ノードからのリクエストに対する応答処理を行う |
\\ ==== onConnect ==== package App; sub onconnect { my $self = shift; ## (1) 初期処理 : : ## (2) アプリケーションハンドラに呼び出す処理を設定 $self->setapphandler( sub { $bbs->App::appmain() } ); } $bbs->setapphandler( 'onConnect', sub { $bbs->App::onconnect(@_) } ); 新たなノードが接続するとonConnectハンドラが呼び出されます。\\ このハンドラではおおむねアプリケーションの初期処理(サーバに対するステータスの更新やノードに対する初期パラメータの設定など)やアプリケーション処理ハンドラ(AppWork)で呼び出すルーチンの設定などを行います。\\ このハンドラは接続するノードに対して1回しか呼び出されません。\\ そのためアプリケーション処理ハンドラ(AppWork)に呼び出すルーチンを設定していないとサーバは応答しなくなります。\\ このハンドラは複数のルーチンを設定することができますが、ルーチン設定の際、重複チェックを行っていないので、重複して登録するとその分、繰り返し呼び出されます。\\ onConnectハンドラのハンドラ設定はサーバ開始前に関数[[projects:bbs_pm:docs:bbs:h_setsyshandler|setsyshandler()]]を呼び出して行います。\\ \\ ==== onDisconnect ==== package App; sub ondisconnect { my $self = shift; ## 終了処理 : : } $bbs->setapphandler( 'onDisconnect', sub { $bbs->App::ondisconnect(@_) } ); onDisconnectハンドラはノードが切断を試みたときに呼び出されます。\\ このハンドラではおおむね切断するユーザに対する終了処理とサーバに対するステータス更新などを行います。\\ このハンドラは複数のルーチンを設定することができますが、ルーチン設定の際、重複チェックを行っていないので、重複して登録するとその分、繰り返し呼び出されます。\\ このハンドラは接続するノードに対して1回しか呼び出されません。\\ onDisconnectハンドラのハンドラ設定はサーバ開始前に関数[[projects:bbs_pm:docs:bbs:h_setsyshandler|setsyshandler()]]を呼び出して行います。\\ \\ ==== onRecv ==== package App; sub onrecv { my $self = shift; my $data = shift; # 受信データ ## 受信データ処理 : : } $bbs->setapphandler( 'onRecv', sub { $bbs->App::onrecv(@_) } ); onRecvハンドラはノードからデータを受信したときに呼び出されます。\\ ノードから通信が行われるとonAccessイベントが発生し受信データの取得を試みます。\\ このときにデータを取得するとonRecvイベントが発生します。\\ onRecvイベントでは取得した受信データを引数に設定されているのでハンドラ内からデータを受け取ります。\\ 受信データを受け取らずハンドラを抜けるとデータを取りこぼすことになり二度と取得することはできません。\\ 作成するサーバアプリケーションの仕様にもよりますが、受信データを他のハンドラで使用する場合はデータをバッファリングする必要がありますが、受信データをバッファリングする処理はBBS.pmでは用意していないため、作成するサーバアプリケーションの仕様に適した処理を定義します。\\ 詳細は[[004#受信処理|こちら]]をご覧ください。\\ このハンドラに設定できるルーチンは1つのみです。\\ onRecvハンドラのハンドラ設定はサーバ開始前に関数[[projects:bbs_pm:docs:bbs:h_setsyshandler|setsyshandler()]]を呼び出して行います。\\ \\ ==== onSend ==== package App; sub onsend { my $self = shift; my $data = shift; # 送信データ ## 送信データ処理 : : ## 送信データのバッファリング : : } $bbs->setapphandler( 'onSend', sub { $bbs->App::onsend(@_) } ); onSendハンドラは関数[[projects:bbs_pm:docs:bbs:c_send|send()]]を呼び出したときに呼び出されます。\\ 関数[[projects:bbs_pm:docs:bbs:c_send|send()]]ではノードに送出するデータが引数として設定されているので、ハンドラ内からデータを受け取ります。\\ 受け取ったデータはこのハンドラからは送出することはできません。\\ データの送出は[[#Output|Output]]ハンドラで行われるため、それまでの間、送出データをバッファリングする必要があります。\\ ただし送出データをバッファリングする処理はBBS.pmでは用意していないため、作成するサーバアプリケーションの仕様に適した処理を定義します。\\ 詳細は[[004#送信処理|こちら]]をご覧ください。\\ このハンドラに設定できるルーチンは1つのみです。\\ onSendハンドラのハンドラ設定はサーバ開始前に関数[[projects:bbs_pm:docs:bbs:h_setsyshandler|setsyshandler()]]を呼び出して行います。\\ \\ ==== Output ==== package App; sub output { my $self = shift; ## 送信データ準備 my $data; # 送出データ : : ## 送出データを返り値にセット return $data; } $bbs->setapphandler( 'Output', sub { $bbs->App::output(@_) } ); Outputハンドラはノードに対する出力処理(Output)が行われるときに呼び出されます。\\ このハンドラでは送出するデータをルーチンの返り値に設定してルーチンを抜け、 呼び出し元のイベント処理にデータが渡るとデータが送出されます。\\ データを送出するためには送出するデータを準備する必要ありますが、送出するデータは前述、onSendハンドラでバッファリングしたデータがここで取り出されることを想定しています。\\ ただし、バッファリングデータを取り出す処理はBBS.pmでは用意していないため、作成するサーバアプリケーションの仕様に適した処理を定義します。\\ 詳細は[[004#送信処理|こちら]]をご覧ください。\\ このハンドラに設定できるルーチンは1つのみです。\\ Outputハンドラのハンドラ設定はサーバ開始前に関数[[projects:bbs_pm:docs:bbs:h_setsyshandler|setsyshandler()]]を呼び出して行います。\\ s\\ ==== AppWork ==== package App; sub appmain { my $self = shift; ## アプリケーション処理(1) : : } AppWorkハンドラはアプリケーション処理が行われるときに呼び出されます。\\ このハンドラではアプリケーション処理を行います。\\ このハンドラはノードが新たに接続したときにノードに対して1つずつ用意されます。\\ このハンドラに設定できるルーチンは1つのみで、サーバ実行中に関数[[projects:bbs_pm:docs:bbs:h_setapphandler|setapphandler()]]を呼び出して行います。\\ 前述、onConnectハンドラではノードが接続したときに呼び出すアプリケーション処理をAppWorkハンドラに設定する必要があり、設定していない場合は応答しなくなります。\\ このハンドラでは呼び出される処理から次に呼び出す処理を設定し、これによりさまざまな振る舞いを変えることができます。\\ \\ ===== ハンドラの特徴と動作 ===== 設定可能なルーチンが1つのみのハンドラ(onRecv, onSend, Output, AppWork )では、 一度ルーチンを設定すると新たなルーチンを設定(上書き)することはできますが、設定しているルーチンの取り消し(無効化)はできません。\\ ルーチンを複数設定できるハンドラ(onConnect, onDisconnect, SysWork)では、一度ルーチンを設定するとルーチンの取り消し(無効化)を行うことができません。また、同じルーチンを重複して設定した場合、それぞれ別々のルーチンとして解釈されるため、ハンドラの呼び出しが行われると同じルーチンがそれぞれ呼び出されます。\\ ハンドラに設定したルーチンはイベントが発生するごとに設定されているルーチンが呼び出されます。 ~~DISCUSSION~~