RFC-6455 The WebSocket Protocol浅読

4754 ワード

WebSokcetとは?
WebSocketはプロトコルであり、各主流ブラウザがクライアントとしてサポートするプロトコルである.XMLHTTPRequestと長いポーリングに基づくソリューションの代わりに使用することを目標としています.時々弾幕、メッセージプッシュ、将棋ゲームなど、タイムリーな通信が必要なビジネスシーンに応用されます.
握手する
WebSocket接続には、握手(handshake)とデータ転送(data transfer)の2つのフェーズがあります.この握手はTCPの3回の握手ではありませんが、目的の差は多くありません.クライアントがブラウザにWebSocketプロトコルを使って通信したいと言ったことです.クライアントは、HTTP Upgradeリクエストである次のリクエストを送信する必要があります.
 GET /chat HTTP/1.1
 Host: server.example.com
 Upgrade: websocket
 Connection: Upgrade
 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
 Origin: http://example.com
 Sec-WebSocket-Protocol: chat, superchat
 Sec-WebSocket-Version: 13

握手が成功すると、サーバは次のように応答します.
 HTTP/1.1 101 Switching Protocols
 Upgrade: websocket
 Connection: Upgrade
 Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
 Sec-WebSocket-Protocol: chat

クライアントが握手リクエストを送信
  • Uriは、
  • のフォーマットを満たす必要があります.
    ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
    wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
  • サービス側との接続が確立されると、クライアントは、HTTPのアップグレードプロトコル(Upgrade)要求である握手要求を送信しなければならない.要求を満たす必要があります
  • 握手リクエストは通常のHTTPリクエストでなければなりません.
  • 要求方法はGETである必要があり、HTTPプロトコルは最低1.1
  • である.
  • 要求ヘッダは、Host
  • を含む必要がある.
  • 要求ヘッダは、Upgradeを含む必要があり、値はwebsocket
  • である.
  • 要求ヘッダに接続を含める必要があります.値はUpgrade
  • です.
  • 要求ヘッダは、Base 64によって変換された長さ16バイトのデータのセット
  • の値であるSec-WebSocket-Keyを含む必要がある.
  • リクエストヘッダにはOriginが含まれている必要があります.クライアントがブラウザであれば、この値は必ずあります.ブラウザでないクライアントであれば、この値は任意に変更できます.
  • 要求ヘッダは、Sec-WebSocket-Versionを含む必要があります.値は13
  • です.
  • 要求ヘッダは、サービス側クライアントが使用したいサブプロトコルを示すSec-WebSocket-Protocolを有することができ、複数はカンマで
  • に分割される.
  • 要求ヘッダは、サービス側クライアントがサポートするプロトコルレベルの拡張を示すSec−WebSocket−Extensionsを有することができる.
  • 要求ヘッダは、Cookie、Authenticationなどの権限検証に関連するヘッダ
  • を有することができる.

    クライアントが握手リクエストを送信すると、サービス側の応答が待たれます.サービス側が正常に応答した後、クライアントは次の検証を行う必要があります.
  • が返すレスポンスコード非101、例えば401500403503等、クライアント接続失敗
  • が返す応答ヘッダには、UpgradeまたはUpgradeの値が含まれていないwebsocketではなく、クライアント接続に失敗した
  • が返す応答ヘッダにConnectionが含まれていない、またはConnectionの値がUpgradeではない、クライアント接続に失敗した
  • が返す応答ヘッダは、Sec-WebSocket-AcceptまたはSec-WebSocket-Acceptの値を含まないBase64(SHA1(Sec-WebSocket-Key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))ではなく、クライアント接続に失敗した
  • である.
  • が返す応答ヘッダSec-WebSocket-Extensionsの値は、クライアントが送信したSec-WebSocket-Extensionsの値ではなく、クライアント接続に失敗した
  • である.
  • が返す応答ヘッダSec-WebSocket-Protocolの値は、クライアントが送信したSec-WebSocket-Protocolの値ではなく、クライアント接続に失敗した
  • である.
    サービス側が握手リクエストを受信サービス側がリクエストの処理中に何も満たさない場合、サービス側はリクエストの処理を終了します.
  • はHTTP 1でなければならない.1+のGETリクエスト
  • は、Host要求ヘッダ
  • を含む.
  • は、Upgrade値がWebSocketである要求ヘッダ
  • を含む.
  • は、Connection値がUpgradeである要求ヘッダ
  • を含む.
  • は、Sec-WebSocket-Key値が16バイト長のBase 64文字列
  • を含む.
  • は、Sec-WebSocket-Version値が13の要求ヘッダ
  • を含む
  • 非必須:Origin
  • 非必須:Sec-WebSocket-Protocol
  • 非必須:Sec-WebSocket-Extensions
  • サービス側がこれが正常な握手要求であり、この要求を処理したいと判断した場合、サービス側はHTTP応答に応答する必要がある.
  • ステータスコードは101 Switching Protocol
  • である必要があります.
  • Upgrade:WebSocket
  • Connection:Upgrade
  • Sec-WebSocket-Acceptは、上記のようにBase64(SHA1(Sec-WebSocket-Key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
  • の値です.
  • Sec-WebSocket-Protocol、クライアントから送信された値
  • Sec-WebSocket-Extensions、クライアントから送信された値
  • これで握手は終わりです.接続状態CONNECTINGからOPEN
    プロトコルフレーム
    WebSocketのプロトコルフレームフォーマットは次のとおりです.
  • FIN 1 bitパケット終了フラグ、1は最後のメッセージパケット、0はあるメッセージパケット
  • を表す.
  • RSV 1,RSV 2,RSV 3:各1 bit,合計3 bit値は0であり、プロトコル拡張(Extensions)が0以外の値の意味を宣言しない限り.サービス側が0以外の値を受信し、対応する定義がない場合、サービス側は直接接続を終了します.
  • Opcode 4 bit x 0後続フレームx 1テキストフレームx 2バイナリフレームx 3-X 7非制御フレーム予約x 8接続x 9 PING xA PONG xB-xF制御フレーム予約
  • を閉じる.
  • Mask 1 bitマスクするかどうか.クライアントがサーバに送信するには、マスクが必要です.サービス側は、マスクを必要としない
  • をクライアントに送信する.
  • PayLoad Length 7 bits,7+16 bits,7+64 bits,値が0-125の場合、パケット長は0-125となる.値が126の場合、後2バイトはパケット長:16 bitとなります.値が127の場合、後8バイトはパケット長:64 bitとなります.
  • Masking-Key, 0-4bits.値があるかどうかは、Mask識別ビットが1であるかどうかによって決まる.
  • Extension data X bytes握手時に拡張を協議した場合、値があります.そうしないと0
  • です.
  • Application data y bytes残りパケット
  • PayLoad data(x+y)bytes総メッセージパケット=Extension data+Application data.マスクがある場合、復号式は次のとおりです:
  • body[i] = body[i] ^ body[i % 4]

    コード解析
    次にtio コードで上記の内容を説明します.具体的なコードにこだわる必要はありません.コード機能を大体理解すればいいです.具体的なプロトコルアップグレードコードは以下の通りである:以上が握手部Httpプロトコルアップグレードプロセスのコード部分である.難解な点はなく、文書の要求に応じて実現すればよい.ただし、ここではプロトコルをアップグレードするプロセスであり、アクセス権の検証に失敗するなど、他のビジネス処理がある場合は、HttpStatusCode 401に直接戻ることができる.
    プロトコルフレームの解析:
    まとめ
    RFC-6455文書を大まかに過ぎると、公式文書で説明したほうが詳しくてはっきりしていることがわかりますが、英語のレベルが合わず、理解が難しい部分もあります.
    参考資料
    RFC-6455