~~NOTOC~~ ---json { "canonical":"projects:bbs_pm:docs:bbs:io:input", "title":"Input", "description":"Input" } --- \\ ====== Input ====== 入力制御モジュール(Input)は、ノードからの受信データを処理するためのモジュールです。\\ このモジュールはパソコン通信における入力処理をエミュレートしたもので、 特にキーボード入力からコマンドやメッセージなどの文字列を取得することができるほか、 入力データをエコーバックする際のデータ変換処理などを行います。 このモジュールには受信バッファと入力バッファを備え、ノードから受信したデータは、一旦、受信バッファに取り込まれます。\\ 受信バッファに取り込まれたデータに訂正処理を施したのち入力バッファに移されることで、コマンドやメッセージなどのテキストデータやパケットなどのバイナリデータとして得ることができるようになります。\\ 本モジュールのバッファ処理は[[#|Buffer(バッファ制御)]]を使用しています。\\
^ 関数名 ^ 説明 ^ | [[.:new|new()]] | オブジェクトを作成します | | [[.:init|_init()]] | 属性を初期化します | | [[.:keyin|keyin()]] | 受信バッファからデータを抜き出します | | [[.:getchar|getchar()]] | 受信バッファから一文字取り出します | | [[.:clear|clear()]] | 入力バッファを消去します | | [[.:store|store()]] | 受信バッファにデータを取り込みます | | [[.:config|config()]] | 動作モードの設定または設定値を取得をします | | [[.:status|status()]] | ステータスを取得します | | [[.:input|input()]] | 入力バッファの内容を返します | | [[.:inkey|inkey()]] | 受信バッファから取得した文字を返します | | [[.:iscr|iscr()]] | 改行フラグの状態を返します | | [[.:isof|isof()]] | オーバーフローフラグの状態を返します | | [[.:len|len()]] | 入力バッファの文字長を返します(ラインモード有効時) | | [[.:cp932len|cp932len()]] | UTF-8文字列からCP932文字列のデータ長を返します |\\ ===== 使い方 ===== \\ ==== (1) 新たなクライアントが接続したらオブジェクトを作成しモジュールが使用できるよう準備します。 ====
use BBS::IO::Input;
sub onconnect {
my $self = shift;
my $me = $self->from(); # 新たに接続したノードのノード番号を取得
my $in = new BBS::IO::Input(); # オブジェクトを作成する
$in->config( 'echo' => 1 ); # 動作モードを設定(エコーバックモードを有効)
$self->node($me)->{'_Input'} = $in; # オブジェクトをノードテーブルに保存
}
上記コードでは新たに接続したノードに対し、オブジェクトを作成、エコーバックモードを有効に変更したあと作成したオブジェクトをノードテーブルに保存します。\\
作成したオブジェクトはノードテーブルに保管しておく方法が最も簡単で、ノードテーブルはノードが切断したとき、ノードテーブルに保持されていたパラメータがすべて自動廃棄されるので、オブジェクト自ら廃棄を行う必要がありません。\\
\\
==== (2) ノードからデータを受信したら受信データを受信バッファに取り込みます。====
sub onrecv {
my $self = shift;
my $data = shift; # 受信データを取得
my $me = $self->from(); # データ送信元のノード番号を取得
my $in = $self->node($me)->{'_Input'}; # 対象ノードのデータ領域(ノードテーブル)からのオブジェクトを取得
$in->store( $data ); # 受け取ったデータを受信バッファに取り込む
}
上記コードではノードからデータを受信したとき、受信データをモジュール内の受信バッファに取り込みます。\\
ノードからデータを受信するとonrecvハンドラが呼び出されます。\\
onrecvハンドラは受信データが引数として設定されているので、ハンドラルーチンからデータを受け取ります。\\
受け取った受信データは関数store()を呼び出し、モジュール内の受信バッファに取り込みます。\\
\\
==== (3) 受信バッファからデータを取り出します。====
sub app {
my $self = shift;
my $me = $self->from(); # データ送信元のノード番号を取得
my $in = $self->node($me)->{'_Input'}; # 対象ノードのデータ領域(ノードテーブル)からのオブジェクトを取得
my $echoback = $in->keyin(); # 入力制御オブジェクトの受信バッファから1文字取得
$self->from_send( $echoback ) if ( defined($echoback) ); # エコーバック文字列を返したらノードに送出
}
上記コードではアプリケーション処理イベントが発生すると受信バッファからデータを取り出します。\\
受信バッファに取り込まれたデータは関数keyin()を呼び出すことで取り出され、データの訂正や補正処理が行われます。\\
処理が施されたデータは入力バッファに移動し、入力した(押されたキーの)文字コードやコマンドやメッセージなどの文字列として取得できるようになります。\\
関数keyin()を呼び出したとき、エコーバックモードが有効の場合はエコーバック文字列が返りますので、コールバック文字列を受け取るとノードに対してエコーバック文字列を送出します。\\
別のケースとして、次のコードではアプリケーション処理イベントが発生するごとに
受信バッファからデータが取り出され、取り出したデータが入力バッファに取り込まれます。\\
受信バッファから取り出したデータが改行の場合、入力バッファの内容を文字列として返します。\\
sub app {
my $self = shift;
my $me = $self->from(); # 対象ノードのノード番号を取得
my $in = $self->node($me)->{'__Input'}; # 入力制御オブジェクト
my $echoback = $in->keyin(); # オブジェクトの受信バッファからデータを取得
my $inkey = $in->inkey(); # 入力した(押されたキーの)文字コードを取得
return unless ( defined($inkey) ); # 何も入力されていなければ終了
if ( defined($echoback) ) # エコーバック文字列を返したら
$self->send( $me, decode('utf8',$echoback), 2 ); # エコーバック文字列をノードに送出
}
if ( $in->iscr() == 1 ) { # 改行を入力したら
my $input = $in->input(); # 入力バッファの内容を取得
$self->send( $me, 'Input=['.$input."]\r\n" ); # 入力バッファの内容をノードに送出
}
}
\\
===== 注意すべきこと =====
受信データは受信バッファに取り込まれますが、受信データは関数keyin()が呼び出されるまで、蓄積されてゆきます。\\
バッファを肥大化させると、バッファがオーバーフローしシステムに不具合が生じる可能性がありますので、バッファの取り込みと取り出しをバランスよく行うように配慮してください。\\
~~DISCUSSION~~