Node.js + Socket.IOでチャットシステム (第2回) - tatsyblog
さて、前回の記事では、node.js (+ express)の環境構築と、チャット画面の出力を行いました。
前回の記事はこちらからご覧になれます。
さて、今回はいよいよSocket.IO にご登場いただき、インタラクティブ・ウェブのドアを叩きたいと思います。
Step 4: socket.ioのテスト まずはローカル環境にSocket.IO のインストールを行います。前回同様に
$ npm install --save socket.io
とコマンドを打ってpackage.json のdependencies も同時に更新してあげます。
次にindex.js の更新です。まずはソースコードを載せます。
// index.js
var express = require ( 'express' );
var app = express ();
var http = require ( 'http' ). Server ( app );
var io = require ( 'socket.io' )( http );
app . get ( '/' , function ( req , res ) {
res . sendFile ( __dirname + '/index.html' );
});
io . on ( 'connection' , function ( socket ) {
console . log ( 'a user connected' );
});
http . listen ( 3000 , function () {
console . log ( 'listening on *:3000' );
});
新しく追加されたのはSocket.IO モジュールの呼び出しとio.on です。
Socket.IO モジュールはサーバーオブジェクトを引数にとる関数を返してきますので、その関数にサーバーオブジェクト(コード中ではhttp )を渡してあげます。
Socket.IO にはいくつかのイベントがあらかじめ用意されていて、その一つがconnection です。イベントへのコールバック関数の登録は**on(eventName, callback)**という関数で行います。
今回のコードでは、クライアントがサーバーに接続した際にlogを出力するという単純なものです。
さて、これでリモート側はOKなのですが、クライアントが開くindex.html 側でconnection イベントが起こったことをindex.js に知らせる必要があります。
そのためにindex.html の**
**の直前に次のコードを追加します。
< script type = "text/javascript" >
var socket = io ();
</ script >
このコードでの注目点は2つです。
1つ目はsocket.io.js というファイルが新しくロードされていること。このファイルは自前で用意して適切な位置に配置する必要はなく 、index.js を呼び出すと自動的にサーバーのこの位置にファイルが自動生成されます。
次にio オブジェクトのインスタンス化ですが、このインスタンス化によりconnection イベントが呼び出されます。
この変更点を加えると、ブラウザでページを開いたときに**“a user connected”という文字列が 「コンソール上」**に表示されるようになります。
またindex.js でio.on を次のように書き換えることで、クライアントが接続を切ったイベントを補足することもできます。
io . on ( 'connection' , function ( socket ) {
console . log ( 'a user connected' );
socket . on ( 'disconnect' , function () {
console . log ( 'user disconnected' );
});
});
Step 5: emitイベント 次にSocket.IO のとても大事な機能であるemit イベントを使ってみます。このイベントはクライアント側で呼び出されると、それがnode.js のサーバーで捕捉されて、何等かの処理を行うことができます。
まずindex.html を次のように書き換えて、button が押されたときに、emit イベントが発生するようにします。
ここではjQuery を使っているのと、ボタンを押すと同時にチャット用input の内容がクリアしていることに注意してください。
< script src = "http://code.jquery.com/jquery-1.11.1.js" ></ script >
< script >
var socket = io ();
$ ( 'form' ). submit ( function (){
socket . emit ( 'chat message' , $ ( '#m' ). val ());
$ ( '#m' ). val ( '' );
return false ;
});
</ script >
一方index.js の方ではsocket.on でhtml側から投げられる**‘chat message’**というイベントを補足して処理します(この’chat message’という名前は任意です )。
io . on ( 'connection' , function ( socket ) {
console . log ( 'a user connected' );
socket . on ( 'disconnect' , function () {
console . log ( 'user disconnected' );
});
socket . on ( 'chat message' , function ( msg ) {
console . log ( 'message: ' + msg );
});
});
すると、メッセージを入力して、Sendボタンを押すたびに「コンソール上」にメッセージが表示されるようになります(あまり嬉しくない)。
Step 6: ブラウザ上でのメッセージ表示 さて、ここまでひたすらコンソール上に文字を出力してきたわけですが、実際にブラウザ上で文字が出力されなければ全くうれしくないわけです。
先ほどはクライアント側からio.emit で**‘chat message’というイベントを投げましたが、実は io.emit**は逆方向、すなわちリモートからクライアントへイベントを投げることも可能です。
そこで、クライアントから**‘chat message’イベントを捕捉したら、送られてきたメッセージを現在つないでいるクライアントに対して同じく ‘chat message’イベントとして emit**します。
io . on ( 'connection' , function ( socket ) {
console . log ( 'a user connected' );
socket . on ( 'disconnect' , function () {
console . log ( 'user disconnected' );
});
socket . on ( 'chat message' , function ( msg ) {
console . log ( 'message: ' + msg );
io . emit ( 'chat message' , msg );
});
});
そうしたらindex.html 側では**‘chat message’イベントを捕捉して、ul#messages に対してメッセージを append**します。
var socket = io();
$('form').submit(function() {
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg) {
$('#messages').append($('< li > ').text(msg));
});
</ script >
これでようやく以下のようなチャット画面を得ることができます。めでたしめでたし。
ちなみに、1つのブラウザでやってもあまり面白くないですが、複数のブラウザや複数のタブでチャットをすると、ちゃんと他の発言が全体に対して送信されていることが分かります。
さて、ここまではSocket.IO のチュートリアルをなぞっているだけでしたが、次回からは少しこのチャットシステムをいじって遊んでみます。
それでは、今回も最後までお読みいただき、ありがとうございました。
とある大学で細々と研究をしております