Windows 8 Consumer PreviewのWebSocket

Windows 8 CPおよびServer Betaでは、IE10を含むすべてのMicrosoft WebSocketクライアントおよびサーバーが、 IETF WebSocketプロトコルの最終バージョンをサポートするようになりました。 さらに、IE10はW3C WebSockets APIの予備的な推奨事項を実装しています



WebSocketは安定しており、開発者は革新的なアプリケーションとサービスの作成を開始できます。 この記事は、以下のW3C WebSockets APIとWebSocketプロトコルの簡単な紹介です。 更新されたFlipbookデモでは、最新のAPIとプロトコルが使用されます。



以前の記事で、 WebSocketを使用するシナリオについて説明しました。

WebSocketを使用すると、Webアプリケーションは通知と更新をリアルタイムで直接ブラウザに配信できます。 開発者は、リアルタイムシナリオ向けに設計されていない個々のHTTP要求/応答相互作用モデルの制限を回避する必要性に関連する問題に直面しています。 WebSocketを使用すると、ブラウザはサーバー側サービスとの双方向の全二重通信チャネルを開くことができます。 各チャネルはこのチャネルを使用して、すぐに反対側にデータを配信できます。 ソーシャルネットワークやゲームから始まり、金融サイトで終わる今日のサイトは、理想的には異なるブラウザーで同じマークアップを使用して、以前よりも優れたリアルタイムシナリオを提供できます。


2011年9月にその記事が公開されて以来、ワーキンググループは重要な進歩を遂げてきました。 WebSocketプロトコルは、IETFによって提案された標準プロトコルになりました。 さらに、W3C WebSockets APIは現在、W3Cの推奨候補です。



Echoを例として使用したWebSocket APIの紹介



以下のコードスニペットは、ASP.NETのSystem.Web.WebSockets名前空間を使用して作成された単純なエコーサーバーを使用して、アプリケーションから送信されたテキストメッセージとバイナリメッセージを返します。 このアプリケーションでは、ユーザーは送信するテキストを入力して応答をテキストメッセージとして表示するか、サーバーに送信してバイナリメッセージとして受信できる画像を描画できます。

画像

WebSocketとHTTPポーリングのレイテンシとパフォーマンスの違いを試すより洗練された例は、 Flipbookデモで見ることができます。



WebSocketサーバーへの接続の詳細。



この簡単な説明は、アプリケーションとサーバー間の直接接続を前提としています。 プロキシ経由の接続が設定されている場合、IE10はCONNECT HTTP要求をプロキシに送信することにより接続プロセスを開始します。



WebSocketオブジェクトが作成されると、クライアントとサーバーの間でハンドシェイクが行われ、WebSocket接続が形成されます。

画像



IE10は、HTTP要求をサーバーに送信することにより、ハンドシェイクプロセスを開始します。

  GET / echo HTTP / 1.1
ホスト:example.microsoft.com
アップグレード:websocket
接続:アップグレード
 Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ ==
起源:http://microsoft.com
 Sec-WebSocket-バージョン:13 


このクエリのすべての部分を見てみましょう。



接続プロセスは、標準のHTTP GET要求で始まります。これにより、要求はファイアウォール、プロキシ、およびその他の中間ポイントを通過できます。

  GET / echo HTTP / 1.1
ホスト:example.microsoft.com 


Upgrade HTTPヘッダーは、アプリケーション層プロトコルをHTTPからWebSocketに切り替えるためのサーバーへのリクエストです。

 アップグレード:websocket
接続:アップグレード 


サーバーは、WebSocketプロトコルを理解していることを示すために応答するときに、Sec-WebSocket-Keyヘッダーの値を変換します。

  Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ == 


Originヘッダーは、サーバーがソースベースのセキュリティポリシーを適用できるようにIE10によって構成されます。

 起源:http://microsoft.com 


Sec-WebSocket-Versionヘッダーは、要求されたプロトコルバージョンを識別します。 バージョン13は、IETFによって提案された標準の最終版です。

  Sec-WebSocket-バージョン:13 


サーバーがアプリケーションレベルのプロトコル更新要求を受け入れると、HTTP 101 Switching Protocols応答を返します。

画像

  HTTP / 1.1 101スイッチングプロトコル
アップグレード:websocket
接続:アップグレード 


WebSocketプロトコルを本当に理解していることを示すために、サーバーはクライアント要求からのSec-WebSocket-Keyヘッダー値の標準化された変換を実行し、結果をSec-WebSocket-Acceptヘッダーに返します。

  Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK + xOo = 


その後、IE10はSec-WebSocket-Keyの値をSec-WebSocket-Acceptの値にマップして、サーバーが実際にWebSocketサーバーであって他のサーバーではないことを確認します。



クライアントハンドシェイクは、IE10とサーバー間でTCPを介したHTTP接続を形成します。 サーバーが101応答を返した後、アプリケーション層プロトコルはHTTPからWebSocketsに切り替わり、以前に確立されたTCP接続を使用します。



この切り替え後、インタラクション画面でHTTPは完全に消えます。 軽量WebSocketプロトコルを使用して、いつでもメッセージを両当事者が送受信できるようになりました。

画像



WebSocketサーバーへの接続のプログラミング



WebSocketプロトコルは、HTTPスキームに非常によく似た2つの新しいURIスキームを定義します。







プロキシまたは他の中間エージェントが存在する場合、中間エージェントは保護されたトラフィックに干渉する可能性が低いため、保護された接続の操作が成功する可能性が高くなります。



次のコードスニペットは、WebSocket接続を確立します。

var host = "ws://example.microsoft.com"; var socket = new WebSocket(host);
      
      







ReadyState-Ready ...インストール... Let's Go ...


WebSocket.readyState属性は、接続ステータス(CONNECTING、OPEN、CLOSING、またはCLOSED)を提供します。 WebSocketが作成されたばかりのとき、readyStateはCONNECTINGに設定されます。 接続が成功すると、readyStateがOPENに設定されます。 接続を確立できなかった場合、readyStateはCLOSEDに設定されます。



接続オープンイベントをサブスクライブする


接続が作成されたという通知を受信するには、アプリケーションはオープンイベントにサブスクライブする必要があります。

 socket.onopen = function (openEvent) { document.getElementById("serverStatus").innerHTML = 'Web Socket State::' + 'OPEN'; };
      
      







舞台裏の詳細:メッセージの送受信



ハンドシェイクが成功すると、アプリケーションとサーバーはWebSocketメッセージを交換できます。 メッセージは、メッセージの1つまたは複数のフラグメント(言い換えると、データ「フレーム」)のシーケンスとして形成されます。



各フレームには次のような情報が含まれます。



画像

IE10は、フレームをメッセージ全体に結合してから、スクリプトに渡します。



メッセージの送信と送信のプログラミング



send APIを使用すると、メッセージをUTF-8でエンコードされたテキスト、およびArrayBufferまたはBlobとしてサーバーに送信できます。



たとえば、このコードは、ユーザーが入力したテキストを取得し、テキストメッセージ(UTF-8)としてサーバーに送信します。 このコードは、Websocket.readyStateがOPEN状態にあることを確認します。

 function sendTextMessage() { if (socket.readyState !== WebSocket.OPEN) { return; } var e = document.getElementById("textmessage"); socket.send(e.value); }
      
      





このコードは、ユーザーがキャンバスに描いた画像を受け取り、バイナリメッセージとしてサーバーに送信します。

 function sendBinaryMessage() { if (socket.readyState != WebSocket.OPEN) { return; } var sourceCanvas = document.getElementById('source'); // msToBlob returns a blob object from a canvas image or drawing socket.send(sourceCanvas.msToBlob()); // ... }
      
      







メッセージイベントのサブスクライブ



メッセージを受信するには、アプリケーションはメッセージイベントをサブスクライブする必要があります。 イベントハンドラーは、MessageEvent.dataのデータを含むMessageEventを受け取ります。 データはテキストまたはバイナリメッセージとして受信できます。



バイナリメッセージを受信すると、WebSocket.binaryType属性は、データをBlobまたはArrayBufferとして返すかどうかを制御します。 属性はblobまたはarraybufferに設定できます。



以下の例では、デフォルト値の「blob」を使用しています。



このコードは、Websocketサーバーから画像またはテキストを受け入れます。 データがバイナリの場合、画像を受け取り、ターゲットキャンバスに描画します。 それ以外の場合、UTF-8でエンコードされたテキストを受信し、テキストボックスに表示します。

 socket.onmessage = function (messageEvent) { if (messageEvent.data instanceof Blob) { var destinationCanvas = document.getElementById('destination'); var destinationContext = destinationCanvas.getContext('2d'); var image = new Image(); image.onload = function () { destinationContext.clearRect(0, 0, destinationCanvas.width, destinationCanvas.height); destinationContext.drawImage(image, 0, 0); } image.src = URL.createObjectURL(messageEvent.data); } else { document.getElementById("textresponse").value = messageEvent.data; } };
      
      







WebSocket接続を閉じる方法の詳細。



歓迎の握手と同様に、別れの握手もあります。 任意の関係者(アプリケーションまたはサーバー)がこのプロセスを開始できます。



特別なタイプのフレーム(クロージングフレーム)が反対側に送信されます。 クローズフレームには、オプションのステータスコードとクローズの理由が含まれる場合があります。 プロトコルは、ステータスコードに適切な値をいくつか定義します。 終了フレームの送信者は、終了フレームの後にデータを送信してはなりません。



反対側がクロージングフレームを受け取ると、自身のクロージングフレームで応答します。 終了フレームに複数のメッセージを事前送信できます。

画像



WebSocketのクローズプログラミングとクローズイベントのサブスクライブ



アプリケーションは、クローズAPIを使用してオープン接続で別れハンドシェイクを開始します。

 socket.close(1000, "normal close");
      
      







接続の終了に関する通知を受信するには、アプリケーションは接続終了イベントをサブスクライブする必要があります。

 socket.onclose = function (closeEvent) { document.getElementById("serverStatus").innerHTML = 'Web Socket State::' + 'CLOSED'; };
      
      







close APIは、プロトコルで定義されたリストのステータスコードと説明の2つのオプションパラメータを受け入れます。 ステータスコードは1000、または3000〜4999の範囲である必要があります。接続が閉じられると、readyState属性はCLOSINGに設定されます。 IE10がサーバーから終了フレームを含む応答を受信すると、readyState属性がCLOSEDに設定され、closeイベントが発生します。



Fiddlerを使用してWebSocketsトラフィックを表示する



Fiddlerは、デバッグ用の一般的なHTTPプロキシです。 最近のバージョンでは、WebSocketプロトコルのサポートがいくつか登場しました。 WebSocketハンドシェイクでヘッダー交換を調べることができます。

画像



すべてのWebSocketメッセージもログに記録されます。 以下のスクリーンショットでは、「スパイラル」アプリケーションがテキストメッセージをサーバーに送信し、サーバーがそれを送り返す様子を確認できます。

画像



おわりに



WebSocketについて詳しく知りたい場合は、2011年9月のMicrosoft // Build / conferenceからこれらのセッションを表示できます。



WebSocketサービスを作成するためのMicrosoftテクノロジーに慣れていない場合は、次の記事が参考になります。





今日、WebSocketに基づいて開発を開始し、ご意見をお聞かせください。



—Windows Networking、シニアプログラムマネージャー、Brian Raymor



All Articles