さくらのVPSとPHPでWebSocketをサクっと勉強してみる

2012年1月2日 追記
最新のブラウザに対応したバージョンの記事を書きました。




今回はWebSocketの勉強をしてみます。
とりあえずサクっと動かしてみる事を目的としていますので、あまり細かい事は気にせずに行きたいと思います。

概要

さくらのVPSとPHP5.3でWebSocketのEchoサーバーを構築し、JavaScriptでサーバーに接続し、チャットできる簡単なサンプルを作ってみます。
次の様な記事をあらかじめ見ていたので、今回は対象ブラウザをChromeのみとしました。
http://www.publickey1.jp/blog/10/websocketfirefox_4opera.html

環境
参考:さくらのVPSについて

先日hetemlからさくらのVPSにサーバーを移行しました。
その時私が参考にさせて頂いたのはこちら。
http://tanaka.sakura.ad.jp/archives/001065.html
http://hideichi.com/archives/88

さくらインターネットの社長のBlogの手順の通りiptablesを編集した場合等は、これからPHPで作成するWebSocketサーバー用のポート番号への接続を許可しておいてください。

手順1.PHPでWebSocketサーバー

WebSocketサーバーは当初Perlでつくろうと思っていたのですが、PHPでもライブラリが公開されているという情報を見つけ、面白そうだったのでPHPで構築することにします。


PHP&WebSocketのラリブラリを探し始めて、最初に「phpwebsocket」というPHPのライブラリの情報を見つけたのですが、ライブラリ公開時からWebSocketの仕様が変わっているようで、このライブラリではChromeから接続することは出来ませんでした(JavaScriptでonopenイベントが発生しない)。
http://www.moongift.jp/2010/03/phpwebsocket/


さらに調べていたところ「php-websocket」というライブラリを見つけました(上記ライブラリと名前ほとんど同じですね)。
こちらはWebSocket draft76に対応しているらしくChromeから接続することができました。
しかもエコーサーバーのサンプル付きでしたので、今回はこのサンプルをそのまま使用することにします。
http://siriux.net/2010/08/php-websocket-server/


手順は次の通り

手順1-1 ソース取得

こちらからソースを取得してきます。
https://github.com/nicokaiser/php-websocket

手順1-2 編集

nicokaiser-php-websocket/server/server.php
を次の例のように、ホスト名とポート番号を編集します。(例:「〇〇〇〇.com」でポート番号が「12345」の場合

//変更前
$server = new \WebSocket\Server('localhost', 8000);
//変更後
$server = new \WebSocket\Server('〇〇〇〇.com', 12345);
手順1-3 サーバーを起動

上記で編集したserver.phpを次のような感じで実行します。

# php nicokaiser-php-websocket/server/server.php

実行すると次のような感じで表示されるかと思います。

2011-01-11 12:34:56 [info] Server created


これでサーバーは完了です。
あとはHtmlとJavaScriptを書いてみましょう。


手順2.JavaScriptでサーバーとソケット通信

こちらを参考にさせて頂きました。
http://babukuma.com/2009/12/html5-websocket.html#nord


次のHtmlをindex.htmlとか適当な名前でサーバーに配置してください。
※上記サイトでは省略されていましたので、ちょっと書き足してみました。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script>
	var ws = new WebSocket("ws://〇〇〇〇.com:12345/echo");
	
	ws.onclose = function(event) {
		alert("websocket " + event + " is closed");
	};
	
	ws.onerror = function(event) {
		alert("websocket " + event + " is error");
	};
	
	ws.onopen = function(event) {
		alert("websocket " + event + " is opened");
	};
	
	ws.onmessage = function(event) {
		var chatarea = document.getElementById("chatarea");
		chatarea.value = chatarea.value + "\n" + event.data;
	};

	function send() {
		var msg = document.getElementById("msg");
		ws.send(msg.value);
		msg.value = '';
		return false;
	}
</script>
</head>
<body>

<textarea id="chatarea"></textarea>
<textarea id="msg">hoge</textarea>

<button onclick="send()" />send</button>

</body>
</html>

上記Htmlをちょっとだけ解説すると、
サーバーサイドのserver.phpに次のように記述されているかと思いますが、

$server = new \WebSocket\Server('〇〇〇〇.com', 12345);
$server->registerApplication('echo', \WebSocket\Application\EchoApplication::getInstance());

上記の、「〇〇〇〇.com」「12345」「echo」がJavaScriptに対応しているんだと思います。

var ws = new WebSocket("ws://〇〇〇〇.com:12345/echo");


これでHtmlとJavaScriptは完了です。ブラウザから実行してみましょう。

手順3.実行してみよう

準備が完了しましたので、手順2で配置したHtmlにアクセスしてみましょう。
うまく接続できると、「websocket [object Event] is opened」とアラートが表示され、サーバーのコンソールに「Connected」「Performing handshake」「Handshake sent」とか表示されるかと思います。
次に「send」ボタンをクリックしてみて、「hoge」という文字が右側のtextareaから左側のtextareaに移動すれば成功です。
f:id:y_d:20110111030947j:image


以上でサンプルの作成が完了しました。

こんなの作ってみました

勢いに乗って他にもサンプルを作ってみました。
ブラウザのウィンドウをリサイズした時、同じサイトを見ている人のブラウザのウィンドウをリサイズするサンプルを作ってみました。
奥のPCのウィンドウをマウスを使ってリサイズしているのですが、同時に手前のP­CのウィンドウをJavaScriptとWebSocketを使ってリサイズしています。
若干タイムラグがありますが、手前のPCがネットブックで処理が遅い為です。Core 2 Duoのマシンで実験してみたところ、殆ど遅延せずリサイズされていました。

番外編

phpwebsocketを使えばWebSocket用のサーバー簡単に書けましたが、ActionScript用などの目的でエコーサーバー作るならこのライブラリを使わなくても簡単に書けます。
http://rainyday.blog.so-net.ne.jp/2007-02-18


ただ、Flashの場合socket policy file serverを立てなきゃいけませんので、そちらは自前で実装することになるかと思います。