その2では、まずエコーサーバー作ろうかと思ったが、
大して難易度変わらんと思うので、やっぱりチャットにした。
ws3.pl
#!/usr/bin/perl
use Mojolicious::Lite;
our(%CLIENT);
websocket '/' => sub{
my $self=shift;
$self->on(message => sub{
my $tx=shift;
my($cmd,$mes)=split(/,/,shift,2);
if($cmd eq '1'){
$CLIENT{$tx}=$tx;
print "logon:".$tx."\n";
}elsif($cmd eq '3'){
if($mes=~/^[\w\%\-\.\~\!\*\'\(\)]+$/){
print "message: $mes\n";
foreach my $c(keys(%CLIENT)){
$CLIENT{$c}->send_message($mes);
}
}
}
});
};
app->start;
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
var WS=new WebSocket("ws://127.0.0.1:3000/");
WS.onopen=function(){
WS.send('1');
};
WS.onmessage=function(e){
document.getElementById('chat').value+=decodeURIComponent(e.data)+"\n";
};
function SendMessage(text){
WS.send('3,'+encodeURIComponent(text));
}
</script>
<input id="text"><button onclick="SendMessage(document.getElementById('text').value);document.getElementById('text').value=''">送信</button>
<div><textarea id="chat" style="width:640px;height:480px"></textarea></div>
</body>
</html>
Mojolicious::Lite
を利用すると、strictとwarningsになっちゃうんで、
変数を利用する前に宣言が必要になる。
Perlの利点損なうから、strictとwarnings嫌いなんだがな・・・
手元のMojoliciousはUbuntu 12.04の2系列なんだが、CPANの方は3系列。
多分バージョンの違いと思うんだが、
CPANのMojolicious説明ではサーバーからクライアントへの送信に send を使ってるんだが、機能しなかった。
他所のMojoliciousサンプル見ると、sendではなくsend_message使って送信してたんで試したら送信できた。
あと、Mojo::Transactionにconnectionメソッドがあって、それで接続識別IDが取得できそうなんだが、無理だった。
接続のリファレンスを識別IDにしてハッシュに入れて、受信時に全端末に送信する感じにした。
connectionイベントってのもあるんで、接続開始時に発行されるもんだと思うんだが、
これも機能しなかったんで、ログオン用のメッセージを最初に送って、端末登録はメッセージ受信時にすることにした。
ちゃんとしたチャット作るなら名前の送信もあるから、どっちにしろアプリでログオン用のメッセージ送信するべきではあるかもね。
クライアントの方は、<textarea>に追加していくだけ。
受信はonmessageイベントで取れる。
onmessageイベントに登録する関数には引数としてeventが渡され、event.dataに受信テキストが入ってる。
送受信する文字列はURLエンコードするようにした。
今回の実験で、バージョン3系列と2系列の違いっぽいのが確認できたんで、
本格的に使うのはUbuntuのリポジトリとCPANのバージョンが同じになってからにしたいな・・・
まあ、CPANはしたくないんで、現状で使うなら2系列かなあ・・・