WebSocket クライアントアプリケーションは WebSocket API を使用して、WebSocket プロトコルを経由して WebSocket サーバーと通信します。

註: この機能は Web Workers 内で利用可能です。

この記事のサンプルスニペットは WebSocket チャットクライアント/サーバーサンプルから取得したものです。 コードを見てから、自分で例を試してみてください。この例には現在バグがあります。安全でない WebSocket を使用しようとしていますが、安全な WebSocket を使用するように更新する必要があります。すぐにこれを修正します!

WebSocket オブジェクトの作成

WebSocket プロトコルを使用して通信するには、WebSocket オブジェクトを作成する必要があります。これにより自動的にサーバーへの接続が開かれます。

WebSocket コンストラクタは、1つの必須パラメータと1つのオプションパラメータを受け取ります。

WebSocket WebSocket(
  in DOMString url,
  in optional DOMString protocols
);
url
接続先 URL。これは、WebSocket サーバーが応答する URL である必要があります。
protocols Optional
単一のプロトコル文字列または一連のプロトコル文字列。これらの文字列はサブプロトコルを示すのに使用されるため、単一のサーバーで複数の WebSocket サブプロトコルを実装できます (たとえば、特定の protocol に応じて1つのサーバーで異なるタイプのインタラクションを処理できるようにする)。プロトコル文字列を指定しない場合、空文字列が仮定されます。

コンストラクタは例外をスローすることができます:

SECURITY_ERR
接続が試行されているポートがブロックされています。

コネクションエラー

接続中にエラーが発生した場合、最初に "error" という名前の単純なイベントが WebSocket オブジェクトに送信され (その結果、その onerror ハンドラが呼び出されます)、次に CloseEventWebSocket オブジェクトに送信され (onclose ハンドラが呼び出されます) 接続の終了の理由を示します。

しかし Firefox 11 では、Mozilla プラットフォームからのコンソールに記述的なエラーメッセージが表示され、RFC 6455 の 7.4 節で定義されている Close コードが CloseEvent を通じて受信されるのが一般的です。

この簡単な例では新しい WebSocket を作成し、ws://www.example.com/socketserver のサーバーに接続します。この例では、ソケットの要求で "protocolOne" のカスタムプロトコルが指定されていますが、省略することもできます。

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");

返されると、exampleSocket.readyStateCONNECTING です。接続がデータを転送する準備ができたら、readyStateOPEN になります。

接続を開き、サポートしているプロトコルについて柔軟に対応したい場合は、プロトコルの配列を指定できます。

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", ["protocolOne", "protocolTwo"]);

接続が確立されると (つまり、readyStateOPEN)、exampleSocket.protocol は、サーバーが選択したプロトコルを通知します。

上の例では、wshttp に置き換えられ、同様に wsshttps に置き換わります。WebSocket を確立するには、HTTP アップグレードメカニズムが必要です。したがって、HTTP サーバーを ws://www.example.com または wss://www.example.com としてアドレス指定すると、プロトコルのアップグレード要求が暗黙的に行われます。

サーバーにデータを送信する

接続を開くと、サーバーにデータを送信することができます。 これを行うには、送信するメッセージごとに WebSocket オブジェクトの send() メソッドを呼び出します。

exampleSocket.send("Here's some text that the server is urgently awaiting!");

データを文字列、Blob、または ArrayBuffer として送信することができます。

メモ: バージョン 11より前では、Firefox は文字列としてデータを送信することのみをサポートしていました。

接続の確立は非同期で失敗しやすいため、WebSocket オブジェクトを作成した直後に send() メソッドを呼び出すことは成功するという保証はありません。一度接続が確立されると、データを送信しようとするのは、作業を行うための onopen ハンドラを定義することによって行われます。

exampleSocket.onopen = function (event) {
  exampleSocket.send("Here's some text that the server is urgently awaiting!"); 
};

JSON を使用したオブジェクトの送信

JSON を使用して、合理的に複雑なデータをサーバーに送信するのが便利です。 たとえば、チャットプログラムは JSON でカプセル化されたデータのパケットを使用して実装されたプロトコルを使用して、サーバーとやりとりできます。

// Send text to all users through the server
function sendText() {
  // Construct a msg object containing the data the server needs to process the message from the chat client.
  var msg = {
    type: "message",
    text: document.getElementById("text").value,
    id:   clientID,
    date: Date.now()
  };

  // Send the msg object as a JSON-formatted string.
  exampleSocket.send(JSON.stringify(msg));
  
  // Blank the text input element, ready to receive the next line of text from the user.
  document.getElementById("text").value = "";
}

サーバーからメッセージを受信する

WebSockets はイベント駆動型 API です。メッセージを受信すると、"message" イベントが onmessage 関数に配信されます。受信データの確認を開始するには、次のようにします。

exampleSocket.onmessage = function (event) {
  console.log(event.data);
}

JSON オブジェクトの受信と解釈

まず Using JSON to transmit objects で述べられているチャットクライアントアプリケーションを考えてみましょう。クライアントが受信するデータパケットの種類は次のとおりです。

  • ログインハンドシェイク
  • メッセージテキスト
  • ユーザーリストの更新

これらの受信メッセージを解釈するコードは、次のようになります。

exampleSocket.onmessage = function(event) {
  var f = document.getElementById("chatbox").contentDocument;
  var text = "";
  var msg = JSON.parse(event.data);
  var time = new Date(msg.date);
  var timeStr = time.toLocaleTimeString();
  
  switch(msg.type) {
    case "id":
      clientID = msg.id;
      setUsername();
      break;
    case "username":
      text = "<b>User <em>" + msg.name + "</em> signed in at " + timeStr + "</b><br>";
      break;
    case "message":
      text = "(" + timeStr + ") <b>" + msg.name + "</b>: " + msg.text + "<br>";
      break;
    case "rejectusername":
      text = "<b>Your username has been set to <em>" + msg.name + "</em> because the name you chose is in use.</b><br>"
      break;
    case "userlist":
      var ul = "";
      for (i=0; i < msg.users.length; i++) {
        ul += msg.users[i] + "<br>";
      }
      document.getElementById("userlistbox").innerHTML = ul;
      break;
  }
  
  if (text.length) {
    f.write(text);
    document.getElementById("chatbox").contentWindow.scrollByPages(1);
  }
};

ここで JSON.parse() を使用して JSON オブジェクトを元のオブジェクトに変換し、その内容を調べて処理します。

テキストデータフォーマット

WebSocket 接続を介して受信されるテキストは、UTF-8 形式です。

Gecko 9.0 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6) より前のバージョンでは、有効ではない UTF-8 テキストの一部の文字は、接続を終了させるでしょう。 現在、Gecko はこれらの値を許可しています。

コネクションを閉じる

WebSocket 接続の使用を終了したら、WebSocket メソッド close() を呼び出します。

exampleSocket.close();

接続を閉じて、データがネットワーク上でまだ送信されていないかどうかを判断する前に、ソケットの bufferedAmount 属性を調べると便利です。

セキュリティの考慮事項

混合コンテンツ環境では WebSocket を使用しないでください。つまり、HTTPS を使用もしくはそうでない方法でもロードされたページからセキュアでない WebSocket 接続を開くべきではありません。実際には、Firefox 8 以降を含むいくつかのブラウザでこれを明示的に禁止しています。

ドキュメントのタグと貢献者

このページの貢献者: silverskyvicto, lv7777, hamasaki, ethertank, suzukaze
最終更新者: silverskyvicto,