2006年11月05日

Perl事はじめに走る。

「PHPによるソケットサーバー」はできないことは無い。
しかしいざやろうとするとプログラミング本体はシンプルですむのに
設定とかサーバーのディレクトリー構造とかが分からないとお話にならないようだ。
Perlで必要だったのはソケットの設定のみ

言語統一ということでPHP単独を目指したが
結局シェルにも頼ることになるので
将来的にやるにしてもモジュール版のセーフモードでできないことは
とりあえずPerlで処理する方向にした。
レスポンス型のものはPHP、処理やプログラミングがあるものはPerlということになりそうだ。

というわけで最初に走らせたFlash用サーバーは「借り物ソース寄せ集め」でPerl版サーバーを作ったわけだが
今回は「Perl事始」も含めて
Flash用サーバープロト1を作ることにした。
使うコードは全て完全消化して最適化していく。

まず仕様はPerlの関数を理解することも含めて以下の形にする。
とりあえず特殊コマンド処理はするもののエコーのみ

  • Portはデフォルト7777だがリクエストのgetにより変更可能とする。

  • ソケット生成が成功ないしは失敗たらレスポンスを返して接続は閉じる

  • 時間を記録しタイムアウトがあるならばとりあえず1時間動作させる。

  • ユーザーの接続、メッセージ、切断を全ユーザーに返す

  • 接続時にはIPなどを表示

  • q一文字が任意のユーザーから入力されたとき及びタイムアウトになったらソケットを閉じて終了



一番目の要素はいわゆるFormデータの受付などと共通だ。
データの受け取りだが

http://xo-ox.net/*****.php?port=7777

とすれぱ
PHPの場合は

$_GET["port"]

一行で取得できる。
Perlについて調べるとユニット依存が結構あるようだ。

use CGI;
//
$data = new CGI;
$data->import_names('params');
$port = $params::port;

あるいは

use CGI;
//
$data = new CGI;
$port = $data->param('port');


結構手間だ。但し文法的にオブジェクト識別子が違うだけでPHPと大差無い。
httpで返す場合は

print $data->header("text/html");

などを入れないといけないらしい。
ようするにPerlは元々CGIのためのものではないということだ。

確かにこの一点を見てもPHPがいかにすっきりしているかわかる。
PerlはPerl5以前は「どなたかが作ったライブラリーをお借りする」のが基本だったようだ。
現在はそうしたものがパッケージ化されてたいていインストールされているようなので
必要に応じてクラスを呼ぶ形らしい。

今回はサーバーなので初期処理のためのコストは無視できる。
ようするにPerlはCやdelphi、言語としてのAction Scriptに近く
PHPはhtmlやプレーヤーとしてのFlashに近いとみた。

さてソケットについてだが前回の借り物寄せ集めとはいえ
さしたる命令は使っていない。

とりあえず使うクラスのメンバーや変数だけ資料として記述して今回はしめたい。

サーバーを作る場合重要なのが

close(STDIN); close(STDOUT);
$|=1;

を入れることで
最初のはリクエストの回線切断で
$|」というのは特殊変数で0 以外が代入されると出力をバッファリングしないようになるらしい。
つまりサーバーのようなものの場合エラーコードなども含めて
バッファがたまるとハングするのでこれが必要だということになる。

XMLソケット作成に都合がいいのが

$/ = "\0";

で$/はセパレート文字を意味する。初期値は改行らしい。

ソケット部のユニット宣言は

use IO::Socket;
use IO::Select;

であった。Perlはクラスの選択肢が多いようだがこれが今の標準なのだろう。
詳細についてはCPANを探索する。

IO::Socketのメンバー

socket
socketpair
bind
listen
accept
send
recv
peername (getpeername)
sockname (getsockname)
shutdown


IO::Socket::INET のメンバー

PeerAddr Remote host address [:]
PeerHost Synonym for PeerAddr
PeerPort Remote port or service [()] |
LocalAddr Local host bind address hostname[:port]
LocalHost Synonym for LocalAddr
LocalPort Local host bind port [()] |
Proto Protocol name (or number) "tcp" | "udp" | ...
Type Socket type SOCK_STREAM | SOCK_DGRAM | ...
Listen Queue size for listen
ReuseAddr Set SO_REUSEADDR before binding
Reuse Set SO_REUSEADDR before binding (deprecated, prefer ReuseAddr)
ReusePort Set SO_REUSEPORT before binding
Broadcast Set SO_BROADCAST before binding
Timeout Timeout value for various operations
MultiHomed Try all addresses for multi-homed hosts
Blocking Determine if connection will be blocking mode

IO::Socketだけ宣言してすれば両方使えるようだ。(LocalPortなどが使えた。)

IO::Selectのメンバー

add ( HANDLES )
remove ( HANDLES )
exists ( HANDLE )
handles
can_read ( [ TIMEOUT ] )
can_write ( [ TIMEOUT ] )
has_exception ( [ TIMEOUT ] )
count ()
bits()
select ( READ, WRITE, EXCEPTION [, TIMEOUT ] )


メインループは

while(@ready = $sel->can_read) {
foreach $fh (@ready) {
if($fh == $lsn) {
$new = $lsn->accept;
$sel->add($new);
//
}
else {
 $sel->remove($fh);
 $fh->close;
}
}
}

となる。詳細を中に実装していく。
全員への配信ならば受信時に配列に代入して
その配列があるか無いかで処理すればいいだろう。

ユーザーへの読み書きは

syswrite( [ FILEHANDLE ] , [出力変数] , [出力バイト長]);
sysread( [ FILEHANDLE ] , [入力変数] , [入力バイト長],[始点] ));

あたりを使う。sysreadは動的にメモリー確保がされるようだ。

Flash用のXMLサーバーはいくつかソースが出ていて前回はそれをリファインしただけだったのだが
とりあえず基本項目は理解できたのでもう少し目の行き届いたものを実装する事を考える。
基本的には\0をメッセージに付け加えて返すだけとなる。

いかんせんFlash用サーバーもありきたりなので
いかにコンパクトで効率よく働くかに注力したい。
また、swf生成やAMFはやはりPHPのほうが簡単に出来そうだ。
コントロールはSWF側に任せ
Perlのサーバーは基本機能だけ、つまりトリガーの制御に注力する方向で考える。


posted by Xo_ox at 23:59| Comment(0) | サーバーサイド手習い | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。