Skip to content

Jxck/socket.io-spec

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 

Repository files navigation

Socket.IO protocol

このドキュメントは、クライアントとサーバが Socket.IO コネクションを接続するために、 満たすべきプロトコルとエンコーディングについての仕様です。

プロトコルのバージョン

このドキュメントは、最新であるプロトコルバージョン 1 について記述しています。

バージョン番号は単一の整数であり、プロトコルのバージョンアップ毎にインクリメントされていきます。

概要

Socket.IO は、実際のリアルタイムアプリケーションやゲーム開発の手助けするための いくつかの機能をもつ、WebSocket-like な API を、 多くのブラウザやデバイス上で実現することを目的としています。

  • (古いブラウザやモバイルに対応するための)複数の通信方法サポート
  • 同一接続上での複数ソケットの実現(名前空間)
  • ハートビートによるコネクションの自動切断
  • 送達確認
  • (電波の悪い環境やモバイルのための)バッファ付き再接続のサポート
  • HTTP をベースとした軽量プロトコル

Socket.IO のソケットの構造

Socket.io のクライアントは最初に接続に利用する通信方法を決定します。

Socket.IO のソケットは disconnected, disconnecting, connected, connecting の状態を持ちます。

通信コネクションには closed, closing, open, and opening があります。

Socket.IO の接続の最初には、シンプルな HTTP ハンドシェイクが実行されます。 ハンドシェイクが成功すると、以下の結果がクライアントに送られます。

  • 通信が接続を開始する時に渡される session id
  • ハードビートの送信が期待される間隔の秒数(heartbeat timeout)
  • 通信コネクションが応答しなくなり、ソケットが閉じられたと判断して 通信コネクションを閉じるまでの秒数(close timeout)

この時点で、ソケットは接続されていると考えられ、通信コネクションにコネクションを オープンするようにシグナルがわたります。

通信コネクションが閉じられたら、両端(サーバ/クライアント)はメッセージをバッファし、 コネクションが再開したときに、まとめて送れるように調度良いサイズのフレームにまとめます。

タイムアウト期間内にコネクションが再開しなかったら、ソケットは通信が切断したと判断します。 この時点で、クライアントは新しいハンドシェイクによってソケットの再接続(reconnect)を開始します。

Socket.IO HTTP リクエスト

Socket.IO の HTTP URI は以下のフォーマットです。

[scheme] '://' [host] '/' [namespace] '/' [protocol version] '/' [transport id] '/' [session id] '/' ( '?' [query] )

(古い User Agent との互換のため)使用されるのは GETPOST メソッドだけです。 実際の使用方法は通信方法によって違います。

通信コネクションが使うメインのメソッドは常に GET です。

URI スキーマ

URI スキーマは、クライアントがセキュアな通信を要求しているかに応じて決定されます。 デフォルトは http ですが、推奨は https です。

URI ホスト

Socket.IO サーバが存在するホストです。ブラウザ環境では、この値はデフォルトで クライアントのページを配信したサーバ(location.host)と同じになります。

名前空間(Namespace)

接続しているクライアントは、 Socket.IO リクエストを区分する名前空間を提供します。

この値は全てのクライアントとサーバに対して、デフォルトで socket.io という値が配布されます。

プロトコルバージョン

クライアントは個々に、自身がサポートするリビジョン ID を、開発者がアクセスできる パブリックなインタフェースとして持つ必要があります。

例えば、ブラウザがサポートするプロトコルのバージョンは io.protocolVersion で取得できます。

通信 ID(Transport ID)

以下の通信方法がサポートされています。

  • xhr-polling
  • xhr-multipart
  • htmlfile
  • websocket
  • flashsocket
  • jsonp-polling

クライアントは最初にどの通信を使用するかを決定します。 通常、ブラウザ内で feature detection を用いて決定されます。

ユーザが定義した通信方法を使用することもできます。

クエリ

クエリコンポーネント (eg: ?token=48737481747&) は全ての URL にあるわけではありません。 特定の key は Socket.IO によって予約されています。

  • t: タイムスタンプを保持します。これは特定の古い UA のキャッシュをバイパスするためだけに使用します。
  • disconnect: 切断を要求するトリガーです。

ユーザ定義のクエリコンポーネントも以下のように使用可能です。 例えば ?t=1238141910&token=mytoken は有効なクエリです。

ハンドシェイク

クライアントは以下のような HTTP POST リクエストを発行します。

http://example.com/socket.io/1/

transport idsession id が無かった場合、サーバはこの要求をハンドシェイクが 済んでいない新しいコネクションと判断します。

サーバは異なる 3 種のレスポンスを返すことができます。

  • 401 Unauthorized

サーバが与えられた情報( Cookie ヘッダやカスタムクエリコンポーネントなど)を用いて クライアントの認証を拒否した場合。

レスポンスボディーは必要ありません。

  • 503 Service Unavailable

もしサーバが何らかの理由(過負荷など)で接続を拒否した場合。

レスポンスボディーは必要ありません。

  • 200 OK

ハンドシェイクが成功した場合。

レスポンスボディは、クライアントに付与するセッション ID (sid)、 それに続く、 heartbeat timeout、 connection closing timeout、 そして、サポートする通信方法の : 区切りのリストを含む必要があります。

ハートビートのタイムアウトが含まれていなかった場合('')は、 サーバもクライアントもハートビートの実行を期待しないものと解釈されます。

4d4f185e96a7b:15:10:websocket,xhr-polling.

通信コネクション

一旦ハンドシェイクが完了しそれが成功だった場合、 ハンドシェイク中に決定した通信手段による HTTP の GET リクエストで コネクションがオープンされ実行されます。

通信コネクションは必要に応じて URI を変更することが 可能 です。 ただし、情報が失われない場合に限ります。 例えば、ハンドシェイクの結果通信手方法としてセキュアな websocket が採用された場合は、 URI は以下のようになります。

wss://example.com/socket.io/1/websocket/4d4f185e96a7b

URI は Socket.IO がメッセージをやり取りする上で必要な全ての情報を含んでいます。 (protocol security, namespace, protocol version, transport, など).

メッセージは、次に述べる取り決めにより送受信されます。 どのように メッセージが エンコードされ、フレームにまとめられるかは、通信方法に依存します。 しかし、通常通信がビルトインでもつフレーム技術(単/双方向) が使われるでしょう。

一方向のみの通信

通信コネクションが、単方向通信として初期化される(サーバはクライアントに送信できるが、逆はできない) 場合、 POST リクエストを同じ endpoint URI のサーバに送り返す挙動をとる必要があります。

メッセージ

フレーム処理

websocketflashsocket といった特定の通信方法は、 メッセージを送受信するための軽量なフレーミングのメカニズムを標準で持っています。

例えば xhr-multipart は、一貫性のために標準の MIME フレーミングを使用します。

ビルトインの軽量フレーミングがない場合、そしてメッセージが多重化される場合(i.e: メッセージのバッファリング) 以下のフォーマットが使われます。

`\ufffd` [message lenth] `\ufffd`

これは、通信におけるフレーミングのオーバーヘッドが大きいところで使用されます。 (ie: xhr-polling がサーバにデータを送信する場合)

Encoding

メッセージは送信される前にエンコードされる必要があります。メッセージは以下のような構造です。

[message type] ':' [message id ('+')] ':' [message endpoint] (':' [message data]) 

message type は一桁の整数です。

message id はインクリメンタルな整数です。ACK(省略可能)のために必要です。

もし message id の後に + が続く場合、ACK は Socket.IO に処理されません。

代わりにユーザによって処理されます。

Socket.IO は標準で multiple channels をサポートします。("multiple sockets") 各々のソケットは endpoint で識別されます(省略可能)

(0) Disconnect

切断を知らせるシグナルです。もし特定の endpoint が指定されなかった場合、全てのソケットを切断します。

Examples:

  • /test という endpoint に接続するソケットを切断します。

    0::/test
    
  • 全てのソケットを切断します。

    0
    

(1) Connect

multiple sockets を利用している場合に限り使用します。 endpoint に接続の旨を合図します。 一旦サーバがそれを受信したら、クライアントにエコーバックします。

例えば、クライアントが /test endpoint に接続を試みる場合、以下のようなメッセージが送信されます。

'1::' [path] [query]

Example:

1::/test?my=param

接続に応答するために、サーバはメッセージをエコーバックします。 そうでなければ、サーバはエラーパケットを送信する可能性もあります。

(2) Heartbeat

ハートビートを送信します。ハートビートはサーバと取り決めた間隔以内に送信される必要があります。 その間隔の間のどのタイミングで送信するかはクライアントが決定します。 (もしサーバとの間で heartbeat timeout が 20 秒と決まった場合、 クライアントは 15 秒毎に送信するかもしれません)

(3) Message

'3:' [message id ('+')] ':' [message endpoint] ':' [data]

標準的なメッセージです。

3:1::blabla

(4) JSON Message

'4:' [message id ('+')] ':' [message endpoint] ':' [json]

JSON エンコードされたメッセージです。

4:1::{"a":"b"}

(5) Event

'5:' [message id ('+')] ':' [message endpoint] ':' [json encoded event]

イベントは JSON メッセージと似ています。しかし、 nameargs フィールドを 含む必要があります。 name は文字列、 args は配列です。

以下のイベント名は予約されています。

'message'
'connect'
'disconnect'
'open'
'close'
'error'
'retry'
'reconnect'

クライアント/サーバともに、これらをこのメッセージタイプとすることはできません。

(6) 送達確認(ACK)

'6:::' [message id] '+' [data]

送達確認は message data としてmessage id を含みます。 もし message id の後に + が続いた場合は、イベントメッセージのパケットとして扱われます。

Example 1: 単純な送達確認

6:::4

Example 2: イベントメッセージを含む送達確認

6:::4+["A","B"]

(7) Error

'7::' [endpoint] ':' [reason] '+' [advice]

例えば、サブソケットへのコネクションが認証されなかった場合。

(8) Noop

No operation(なにもしない)。例えば、ポーリングがタイムアウトした時、接続を閉じる場合などに使います。

ソケットの強制切断

Socket.IO サーバは、ソケットを強制切断するための endpoint を提供する必要があります。

通信コネクションを閉じるには、 disconnection イベントをトリガーすれば十分です。 タイムアウトが発生しないのを確認し、 disconnection イベントがすぐに発生することが 望ましい場合もあります。

http://example.com/socket.io/1/xhr-polling/812738127387123?disconnect

サーバは 200 OK か、問題が発生しているのであれば 500 を返す必要があります。

About

Specification for the Socket.IO Protocol

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published