英語の元のページはこちら
前提条件としてnode.jsがインストールされていることが必要です。
node.jsのインストール
cd /tmp curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash - sudo yum -y install nodejs sudo yum -y install gcc-c++ make
package.jsonの作成
cd mkdir chat cd chat vi package.json
package.json
に次の内容を入力します:
{ "name": "socket-chat-example", "version": "0.0.1", "description": "my first socket.io app", "dependencies": {} }
expressのインストール
次にフレームワークのexpressをインストールします。
package.jsonのdependencies
の編集を省略するためにnpm install --save
を実行します:
cd ~/chat npm install --save express@4.15.2
index.jsの作成
次の内容でindex.jsを作成します:
var app = require('express')(); var http = require('http').Server(app); app.get('/', function(req, res){ res.send('<h1>Hello world</h1>'); }); http.listen(3000, function(){ console.log('listening on *:3000'); });
上記の内容ですが、
* app
を、HTTPサーバに渡せる関数ハンドラとして初期化する
* ルートハンドラ/
を定義する。これはウェブページをアクセスした際に呼び出される
* ポート3000でウェブサーバをlistenする
ウェブサーバの起動
node index.js
と実行すると、次の画面が出るはずです:
ここでブラウザをhttp://localhost:3000
に向けると、次のような画面が表示されます:
HTMLを別ファイルに分ける
index.js
では、res.send
に対してHTMLを文字列として渡しています。HTMLが長くなると見通しが悪くなりコードが管理しづらいので、index.html
を作成してそこにHTMLを格納します:
app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); });
index.html
には次の内容を記述します:
<!doctype html> <html> <head> <title>Socket.IO chat</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font: 13px Helvetica, Arial; } form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; } form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; } form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; } #messages { list-style-type: none; margin: 0; padding: 0; } #messages li { padding: 5px 10px; } #messages li:nth-child(odd) { background: #eee; } </style> </head> <body> <ul id="messages"></ul> <form action=""> <input id="m" autocomplete="off" /><button>Send</button> </form> </body> </html>
ここで、node index.js
を再度実行し(ctrl-cで一旦殺してから、再度、実行)ブラウザからhttp://localhost:3000
を
アクセスすると次のような画面が出るはずです:
Socket.IOの組み込み
Socket.IOは次の2つから構成されています:
- Node.JSのHTTPサーバと連動して動く
socket.io
- ブラウザ側で読み込まれるクライアントライブラリ
sockiet.io-client
開発中においては、socket.io
がクライアントに対して自動的にサービスを提供してくれるため、現時点ではsocket.io
のみをインストールします:
npm install --save socket.io
これでsocket.io
がインストールされpackage.json
が更新されます。次に、index.js
を編集しsocket.io
を読み込みます:
var app = require('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'); });
上記ですが、http
オブジェクト(HTTPサーバ)を渡してsocket.io
のインスタンスを初期化しています。
次にconnection
イベントを待ち受け、コンソールに出力しています。
ブラウザ側への組み込み
index.html
を開いて、次のコードを</body>
の直前に入れます:
<script src="/socket.io/socket.io.js"></script> <script> var socket = io(); </script>
これだけでsocket.io-client
を読み込み、io
グローバルを露出し、接続します。
なお、io()
を呼ぶ時URLを指定していませんが、これは、ページを配信したホストにデフォルトで接続するためです。
ここでブラウザを再読込するとコンソールが "a user connected"と出力するはずです。 複数のタブを開くと、次のように複数メッセージが出力されます:
各ソケットは特殊なdisconnect
イベントを発行します:
io.on('connection', function(socket){ console.log('a user connected'); socket.on('disconnect', function(){ console.log('user disconnected'); }); });
ブラウザでリロードを数回行うと、disconnect
を確認できます:
イベントの発行
Socket.IOのコンセプトとして、お好きなイベントの送信・受信ができ、その際、お好きなデータを送れます。JSONでエンコードできるデータであればなんでもOKです。バイナリデータもサポートされています。
さて、ユーザがメッセージを入力したら、サーバがそれを受信してチャットメッセージのイベントを発行するようにしましょう。index.html
の<script>
部分を次のようにします:
<script src="/socket.io/socket.io.js"></script> <script src="https://code.jquery.com/jquery-1.11.1.js"></script> <script> $(function () { var socket = io(); $('form').submit(function(){ socket.emit('chat message', $('#m').val()); $('#m').val(''); return false; }); }); </script>
そしてindex.js
では、chat message
イベントを出力します:
io.on('connection', function(socket){ socket.on('chat message', function(msg){ console.log('message: ' + msg); }); });
結果として次の動画のようになるはずです(元のサイトで動画をご覧ください)
ブロードキャスト
次に、サーバから他のユーザに対してイベントを発行します。
イベントを全員に送るには、socket.io
のio.emit
を利用します:
io.emit('some event', { for: 'everyone' });
もし、特定のソケットを除いてメッセージを送りたい場合、broadcast
フラグを使います:
io.on('connection', function(socket){ socket.broadcast.emit('hi'); });
注:原文の意味がよくわからないのですが、これを使うとメッセージを送信した本人以外にイベントが届きます
今回はわかりやすさのため、送信者を含む全員にメッセージを送ります:
io.on('connection', function(socket){ socket.on('chat message', function(msg){ io.emit('chat message', msg); }); });
クライアント側ではchat message
イベントを受信し、ページ内に表示します:
<script> $(function () { 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>
これで、簡単なチャットが実現できました。
宿題
- 誰かが接続・切断した場合に接続しているユーザに通知を送りましょう
- ニックネーム機能を付けましょう
- 送信者にはメッセージを送らないようにしましょう。代わりに、メッセージ入力後にDOMにすぐに追記します。
- "○○さんが入力中です"の機能をつけましょう
- 誰がオンラインであるかを表示する機能をつけましょう
- 個人間のメッセージを付けましょう
- 改良した内容をみんなと共有しましょう!
このチュートリアルを入手するには
$ git clone https://github.com/socketio/chat-example.git