サーバ側ソースコードの解説
お待たせしました。ではこのSocket.IOを用いてリアルタイムWebのサンプルを作成します。リアルタイムWebのサンプルとしてはありがちなチャットシステムですが、Socket.IOが適切なリアルタイムWeb技術を選択しているところが見て取れます。
今回の検証プログラムは、下記のバージョンで作成しました。
なお、以降のソースコードは省略している部分があります。完全なソースコードは、Tech-Sketchのgithubを参照してください。
index.js
index.jsは、今回のチャットアプリケーションのエントリポイントです。Expressのデフォルトでは"app.js"という名前になりますが、今回利用するPaaSの都合上、index.jsという名前に変更しています。
// ドキュメントルートへのリクエストを./routes/chat.jsのindex関数へルーティング
app.get('/', chat.index);
・・・
// commons.jsで "protocol" というプロパティが定義されている場合、強制的にその仕組みで接続する(websocket, xhr-pollingなど)
if (typeof commons.protocol != 'undefined') {
io.configure(function(){
io.set("transports", [commons.protocol]);
});
}
// Socket.IO APIを用いたサーバ側実装
io.sockets.on("connection", function(socket){
console.log("client connected");
// クライアントから"message"という名前のメッセージを受信したら
socket.on("message", function(data){
// すべてのクライアントへ"broadcast"という名前で受信したメッセージを送信する
console.log("receive messsage -> %j", data);
io.sockets.emit("broadcast", data);
});
socket.on("disconnect", function(){
console.log("client disconnected");
});
});
Socket.IO APIを用いてサーバ側を実装しています。
至ってシンプルで、接続しているいずれかのクライアントから「message」という名前のメッセージを受信したら、現在接続しているすべてのクライアントに「broadcast」という名前で受信したメッセージを送信するだけです。
chat.js
ブラウザから「http://<<サーバ>>/」というリクエストを受け取った際に、このchat.jsのindexが呼び出されます。
exports.index = function(req, res){
// htmlをレンダリングするテンプレート(chat.ejs)に渡すパラメータ
var params = {
title: 'Socket.IO-Client (web)',
host: commons.host
};
// commons.jsで "protocol" というプロパティが定義されている場合、パラメータに追加
if (typeof commons.protocol != 'undefined') {
params.protocol = commons.protocol;
}
res.render('chat', params);
};
パラメータを設定してchat.ejsへHTMLレンダリングを委譲するだけですね。
chat.ejs
chat.ejsは、チャットアプリケーション用HTMLをレンダリングするテンプレートです。
Socket.IOが提供するJavaScriptライブラリを利用してクライアント側の実装を行っています。接続すべきSocket.IOサーバの情報は、chat.jsから渡されたパラメータから得ています。
<script>
<% if (typeof protocol != 'undefined') { %>
var socket = io.connect("<%= host %>", {transports: ["<%= protocol %>"]});
<% } else { %>
var socket = io.connect("<%= host %>");
<% } %>
$(document).ready(function(){
var send = $("#send");
var msg = $("#msg");
var msgArea = $("#msgArea");
// "broadcast"という名前のメッセージを受信したら
socket.on("broadcast", function(data){
// msgAreaに受信したメッセージを追加する
msgArea.append("<div>" + data + "</div>");
});
// sendボタンが押されたら
send.on("click", function(){
// "message"という名前で入力内容を送信する
socket.emit("message", msg.val());
msg.val("");
});
});
</script>
</head>
<body>
<h1><%= title %></h1>
<input type="text" id="msg" placeholder="message here" />
<button id="send">Send</button>
<div id="msgArea"></div>
</body>
socket.on("xxx", function(){...})で受信したメッセージを処理し、socket.emit("xxx", ...)でメッセージを送信します。このメッセージ送受信APIは、サーバ側とほとんど同じであることが分かると思います。
commons.js
最後に、commons.jsです。これはサーバ側のNode.jsアプリケーションがデプロイされたURLとポート、利用するTransport層の実装など、環境ごとに異なる定数を定義します。
module.exports = {
host: "http://techsocketio-nobuyuki.matsui.dotcloud.com",
port: 8080
// , protocol: "xhr-polling"
};
protocolの部分をコメントアウトしている場合、その環境で最適なリアルタイムWeb技術が自動的に選択されます。もし特定のリアルタイムWeb技術に限定して接続させたい場合、コメントアウトを外して対象となるリアルタイムWeb技術を指定してください。
