Introducing

Socket.IO

v.9
Google Groups
Email:

What is Socket.IO?

Socket.IO は複数の通信メカニズムを抽象化することで、 全てのブラウザ、デバイスでリアルタイムアプリを実装可能にするために開発されました。 とても手軽にリアルタイムなアプリを 100% JavaScript で作成可能です。

Server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Client

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

How to use

インストール

npm install socket.io

Node の HTTP サーバと連携する

この例では、単純に `npm install socket.io` を実行するだけです

Server (app.js)

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Client (index.html)

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

Express 3 と連携する

Express 3 は Socket.IO にアタッチする前に、 `http.server` のインスタンスが必要です。

Server (app.js)

var app = require('express')()
  , server = require('http').createServer(app)
  , io = require('socket.io').listen(server);

server.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Client (index.html)

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

Express と連携する

通常のページ配信や、Ajax リクエストは Express で行い、そこに Socket.IO のサーバを加えます。

この例では `npm install socket.io express` を実行してください。

Server (app.js)

var app = require('express').createServer()
  , io = require('socket.io').listen(app);

app.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Client (index.html)

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

メッセージの送受信

Socket.IO はカスタムイベントの発行/検出ができます。`connect`, `message`, `disconnect` に加えて、好きなイベント名を使うことができます。

Server

// note, io.listen(<port>) will create a http server for you
var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  io.sockets.emit('this', { will: 'be received by everyone'});

  socket.on('private message', function (from, msg) {
    console.log('I received a private message by ', from, ' saying ', msg);
  });

  socket.on('disconnect', function () {
    io.sockets.emit('user disconnected');
  });
});

クライアントに紐づいた、データの保持

セッションの保持などのために、クライアントに紐づいたデータを保持する必要がある場合があります。

Server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('set name', function (name) {
    socket.set('name', name, function () {
      socket.emit('ready');
    });
  });

  socket.on('get name', function () {
    socket.get('name', function (err, name) {
      socket.emit('name', name);
    });
  });
});

Client

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');

  socket.on('connect', function() {
    socket.emit('set name', 'rauchg');
    socket.on('ready', function (msg) {
      socket.emit('get name');
    });
    socket.on('name', function (name) {
      console.log('name is', name);
    });
  });
</script>

ネームスペースによる制限

もし特定のアプリケーションに発行される全てのメッセージやイベントの制御が出来るのであれば、デフォルトの / のネームスペースで問題なく動作します。もし、サードパーティのコードを取り入れたり、他のコードと共有したい場合のために、 Socket.IO はソケットに対するネームスペースを提供します。

これは単一コネクション上での `multiplexing(多重通信)` の恩恵であり、二つの `WebSocket` 通信ではなく、一つだけを使って行っています。

Server

var io = require('socket.io').listen(80);

var chat = io
  .of('/chat')
  .on('connection', function (socket) {
    socket.emit('a message', {
        that: 'only'
      , '/chat': 'will get'
    });
    chat.emit('a message', {
        everyone: 'in'
      , '/chat': 'will get'
    });
  });

var news = io
  .of('/news')
  .on('connection', function (socket) {
    socket.emit('item', { news: 'item' });
  });

Client

<script>
  var chat = io.connect('http://localhost/chat')
    , news = io.connect('http://localhost/news');
  
  chat.on('connect', function () {
    chat.emit('hi!');
  });
  
  news.on('news', function () {
    news.emit('woot');
  });
</script>

揮発性メッセージの送信

ときには、メッセージが欠落しても良い場合があります。例えば `bieber` というキーワードのツイートをリアルタイムに表示するアプリが有ったとしましょう。

もし特定のクライアントが(ネットワークの遅延や他の理由、もしくはロングポーリングのリクエスト-レスポンスサイクルの途中だった場合など)メッセージを受信できる状態でなかったとき、別に全部の `bieber` ツイートを受信できてなかったとしても、あまり気になりません。

その場合、メッセージを揮発性メッセージとして送ることができます。

Server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  var tweets = setInterval(function () {
    getBieberTweet(function (tweet) {
      socket.volatile.emit('bieber tweet', tweet);
    });
  }, 100);

  socket.on('disconnect', function () {
    clearInterval(tweets);
  });
});

送達確認

クライアントにメッセージが届いたかどうか、コールバックで知りたい場合があるでしょう。

その場合、単純に `.send` や `.emit` の最後の引数にコールバック関数を渡すだけで済みます。更に、 `.emit` 時には、そのコールバックにデータを渡すことで実行することができます。

Server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('ferret', function (name, fn) {
    fn('woot');
  });
});

Client

<script>
  var socket = io.connect(); // TIP: .connect with no args does auto-discovery
  socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
    socket.emit('ferret', 'tobi', function (data) {
      console.log(data); // data will be 'woot'
    });
  });
</script>

メッセージのブロードキャスト

ブロードキャストは `broadcast` フラグを `emit` や `send` の前に付けるだけです。ブロードキャストとはメッセージを「それを送ってきた人」以外全員に送る事です。

Server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
});

クロスブラウザ WebSocket としての利用

もし本来の WebSocket の構文と同じように使いたかったら、 `send` を使用してメッセージを送り `message` イベントを検出すれば良いだけです。

Server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});

Client

<script>
  var socket = io.connect('http://localhost/');
  socket.on('connect', function () {
    socket.send('hi');

    socket.on('message', function (msg) {
      // my msg
    });
  });
</script>

サポートする通信方法

全てのブラウザでリアルタイムな通信を実現するために、 Socket.IO は API に一切影響を与えることなく、環境に最も適した通信環境を選択します。

  • WebSocket
  • Adobe® Flash® Socket
  • AJAX long polling
  • AJAX multipart streaming
  • Forever Iframe
  • JSONP Polling

Supported browsers

Desktop

  • Internet Explorer 5.5+
  • Safari 3+
  • Google Chrome 4+
  • Firefox 3+
  • Opera 10.61+

Mobile

  • iPhone Safari
  • iPad Safari
  • Android WebKit
  • WebOs WebKit

FAQ

Socket.IO はクロスドメイン通信をサポートしていますか?

全てのブラウザで完璧にサポートしています!

なぜ Flash なんですか?

Flash は実際は Socket.IO の機能に全く 必要ない です。しかし、もし Flash が有効なら、 それを使えば WebSocket とほぼ同等の性能を発揮します。もし無ければ、次の通信方法が選択されるだけです。

Socket.IO のクライアントライブラリを自分でホストしたいのですが。

もし、 Node.js で Socket.IO のクライアントライブラリの JS ファイルを配らないなら、 socket.io.js をインクルードした後に `WEB_SOCKET_SWF_LOCATION` に WebSocketMain.swf のパスを設定するのを忘れないで下さい。

これは Socket.IO が Flash WebSocket の実行時に .swf ファイルの場所を知るために必要です。

なぜ `WebSocket` とは呼ばないんですか? もし実際に WebSocket が使えなくても、その API を真似るため?

Socket.IO は WebSocket より多くの機能を提供します。WebSocket が通信方法に選択され、ユーザが超モダンなブラウザでそのサイトを見ていたとしてもです。例えば、ハートビート、タイムアウトや切断のサポートはリアルタイムアプリを作る上では非常に重要ですが、 WebSocket の API では、そのままでは提供されていません。

これは、 jQuery が $.ajax という多機能かつシンプルな API で通常の XMLHttpRequest を抽象化しているのと同じ考え方です。

Fork me on GitHub