WebSocket in PHP And JS 〜レンタルサーバー上でのWebSocket〜

イントロダクション

ここ数日、WebSocketを実装しようと色々とやりました。結局のところJSでの「WebSocket」を使用すれば簡単に行けることがわかりました。

WebSocket実装について

シンプルにサーバーはPHPでクライアントがJSになります。参考にしたソースはそれぞれ以下のようになっていました。

index.php:クライアント

デザイン的な部分はさておきにして。。。PHPの処理はメッセージの色をランダムに選択する処理を行なっているのみでした。

そして、本題のJS部分に関して

// ウェブソケットの作成処理
var wsUri = "ws://zenryokuservice.com:9000/demo/server.php"; 	
websocket = new WebSocket(wsUri);

ここではURLを設定する時に「ws://」で始める(プロトコル指定)を行いブラウザに実装されている「WebSocket」を作成(new)しています。

そして、作成したWebSocketにイベント処理を追加しています。

websocket.onopen = function(ev) {...};
websocket.onmessage = function(ev) {...};
websocket.onerror = function(ev) {...};
websocket.onclose = function(ev) {...};

送信部分の処理で以下の様になってました。

//prepare json data
var msg = {
	message: message_input.val(),
	name: name_input.val(),
	color : ''
};
websocket.send(JSON.stringify(msg));

そして。。。

サーバーサイドPHP(Socketサーバー)

通常通りにSocketサーバーを作成します。ちなみにJavaでやっても同じ手順を踏んでSocketサーバーを作成します。※java.net.ServerSocket

「通常通りというのは以下の手順です。」

  1. ソケットを作成      php -> socket_create();
  2. オプション設定      php -> socket_set_option();
  3. バインド         php -> socket_bind();
  4. リッスン開始            php -> socket_listen(); ※Javaは「listen」ではない
  5. 受信          php -> socket_accept();
  6. データの読み込み    php -> socket_read();


ここまでが大体ですがJavaでやる時と同じです。※メソッドなどは違います。。。

HTTPヘッダをWebSocket様に書き換えてソケット送信していました。

$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
//hand shaking header
$upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
// 送信処理
socket_write($client_conn,$upgrade,strlen($upgrade));

どうやらここがキーポイントだと思います。まだ調べていないのでなんとも言えませんが、今まで色々と試したことはPOSTリクエストとGETリクエストを送信する処理からイベントハンドラを使用して受信したメッセージを画面に表示するものでした。

なので、受信したデータは画面に表示されませんでした。サーバーで受けてもクライアント側に通知がいかないのでそれは何も起きません。。。

つまるところ、サーバー側からクライアント側にメッセージの受信を通知するためにはHTTPのヘッダメッセージを「Web Socket Protocol Handshake」にしないとダメなのではなかろうか?と疑っているところです。

これをうまく、Pythonからのソケット受信を受けた時にクライアントサイドの画面に表示できる様にしたい。。。

戦いはまだまだ続きます(笑)