2021年12月15日

WebSocket

WebSocket プロトコルは仕様 RFC 6455 で説明されており、これは永続的な接続を介してブラウザとサーバ間でデータを交換する方法を提供します。接続の切断や追加のHTTPリクエストをすることなく、データを “パケット” として双方向に渡すことができます。

WebSocket は継続的にデータ交換を必要とするようなサービスに特に適しています。例えば、オンラインゲームやリアルタイムの取引システムなどです。

簡単な例

websocket の接続を開くには、url の特別なプロトコル ws を使用した new WebSocket を作る必要があります:

let socket = new WebSocket("ws://javascript.info");

暗号化された wss:// プロトコルもあります。websocket の HTTPS 版のようなものです。

常に wss:// が好ましいです

wss:// プロトコルは暗号化されるだけでなく、より信頼性があります。

これは、ws:// のデータは暗号化されておらず、あらゆる仲介者に見えるためです。古いプロキシサーバによっては WebSocket を認識しないため、おかしなヘッダに見え、接続を中止する可能性があります。

一方、wss:// は WebSocket over TLS (HTTPS が HTTP over TLS であるのと同じ)であり、TLS は送信側でデータを暗号化し、受信側で復号化します。そのため、データパケットは暗号化されてプロキシを通過します。プロキシは中身を見ることはできず、それらを通過させます。

ソケットが作成されると、そこで発生するイベントをリッスンする必要があります。全部で4つのイベントがあります。:

  • open – 接続が確立されました,
  • message – データを受け取りました,
  • error – websocket エラー,
  • close – 接続がクローズされました.

…また、なにかを送信したいときは、socket.send(data) で送ることができます。

例:

let socket = new WebSocket("wss://javascript.info/article/websocket/demo/hello");

socket.onopen = function(e) {
  alert("[open] Connection established");
  alert("Sending to server");
  socket.send("My name is John");
};

socket.onmessage = function(event) {
  alert(`[message] Data received from server: ${event.data}`);
};

socket.onclose = function(event) {
  if (event.wasClean) {
    alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
  } else {
    // e.g. サーバのプロセスが停止、あるいはネットワークダウン
    // この場合、event.code は通常 1006 になります
    alert('[close] Connection died');
  }
};

socket.onerror = function(error) {
  alert(`[error] ${error.message}`);
};

デモ用に、上記の例では Node.js で書かれた小さなサーバ server.jsが動作しています。これは “Hello from server, John” と応答し、5秒待ってから接続をクローズします。

なので、 openmessageclose のイベントが表示されるはずです。

これだけです。とても簡単ですね。

では、ここからはより詳しく見ていきましょう。

websocket のオープン

new WebSocket(url) が生成されると、すぐに接続が開始されます。

接続中、ブラウザは(ヘッダを利用して)サーバに問い合わせます: “Websocket をサポートしていますか?”。そしてサーバが “はい” と回答した場合、WebSocket プロトコルでやりとりが続きます。これは HTTP ではありません。

これは new WebSocket("wss://javascript.info/chat") のリクエストにより作成されたブラウザヘッダの例です:

GET /chat
Host: javascript.info
Origin: https://javascript.info
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==
Sec-WebSocket-Version: 13