RFC6455-The WebSocket protocol 之五:Opening Handshake 4.2-4.4

參考:http://jinnianshilongnian.iteye.com/blog/1898350

4.2 Server-Side Requirements
服務器端的要求
   Servers MAY offload the management of the connection to other agents
   on the network, for example, load balancers and reverse proxies.  In
   such a situation, the server for the purposes of this specification
   is considered to include all parts of the server-side infrastructure
   from the first device to terminate the TCP connection all the way to
   the server that processes requests and sends responses.
服務器可能會把連接的管理託管給網絡上的其它代理,比如負載均衡器和反向代理。在這種情況下,本文中提到的服務器包含服務端所有的基礎設施,包括服務器處理請求和響應一直到連接關閉過程中所涉及到的所有設備。

   EXAMPLE: A data center might have a server that responds to WebSocket
   requests with an appropriate handshake and then passes the connection
   to another server to actually process the data frames.  For the
   purposes of this specification, the "server" is the combination of
   both computers.
例如,數據中心的一臺服務器使用正確的握手對WebSocket請求進行了響應,然後把這個連接傳遞給另外一臺服務器,這臺服務器真正處理數據。按照本說明書的定義,“server”指的是這兩臺服務器。

4.2.1.  Reading the Client’s Opening Handshake
讀取客戶端的握手
   When a client starts a WebSocket connection, it sends its part of the
   opening handshake.  The server must parse at least part of this
   handshake in order to obtain the necessary information to generate
   the server part of the handshake.
當一個客戶端建立了WebSocket連接後,它發送握手的部分信息。服務器必須能解析本握手的最小部分的數據,從而可以獲得足夠的信息來生成server端的握手。

   The client’s opening handshake consists of the following parts.  If
   the server, while reading the handshake, finds that the client did
   not send a handshake that matches the description below (note that as
   per [RFC2616], the order of the header fields is not important),
   including but not limited to any violations of the ABNF grammar
   specified for the components of the handshake, the server MUST stop
   processing the client’s handshake and return an HTTP response with an
   appropriate error code (such as 400 Bad Request).
客戶端的握手由以下部分組成。當server在讀取握手信息時,如果發現客戶端發送了一個與以下描述不匹配的握手(注意,頭信息的順序不重要),包括但不僅限於違反了ABNF語法中對握手組件的定義,服務器必須馬上停止處理該握手併發送一個合適的http錯誤代碼(例如400代表錯誤請求)。

   1.   An HTTP/1.1 or higher GET request, including a "Request-URI"
        [RFC2616] that should be interpreted as a /resource name/
        defined in Section 3 (or an absolute HTTP/HTTPS URI containing
        the /resource name/).
1.1及以上版本的包含 "Request-URI"的http get請求,應該被解析成第三種中定義的resource name的格式(或者一個包含resource name的絕對Http/https URI)。

   2.   A |Host| header field containing the server’s authority.
Host頭字段包含了服務器的權限。

   3.   An |Upgrade| header field containing the value "websocket",
        treated as an ASCII case-insensitive value.
包含"websocket"值的Upgrade頭字段,需要按照大小寫不敏感的ASCII碼處理。

   4.   A |Connection| header field that includes the token "Upgrade",
        treated as an ASCII case-insensitive value.
包含"Upgrade"值的Connection頭字段,需要按照大小寫不敏感的ASCII碼處理。

   5.   A |Sec-WebSocket-Key| header field with a base64-encoded (see
        Section 4 of [RFC4648]) value that, when decoded, is 16 bytes in
        length.
含有base64編碼數據的Sec-WebSocket-Key頭字段,解碼後的長度是16位。

   6.   A |Sec-WebSocket-Version| header field, with a value of 13.
Sec-WebSocket-Version頭字段的值爲13.

   7.   Optionally, an |Origin| header field.  This header field is sent
        by all browser clients.  A connection attempt lacking this
        header field SHOULD NOT be interpreted as coming from a browser
        client.
Origin頭字段是可選的。這個字段由瀏覽器類型的客戶端發送。缺少該頭字段的連接,應該被認爲不是來自瀏覽器客戶端。

   8.   Optionally, a |Sec-WebSocket-Protocol| header field, with a list
        of values indicating which protocols the client would like to
        speak, ordered by preference.
Sec-WebSocket-Protocol 頭字段是可選的,其值是客戶端計劃使用的協議的列表,按照優先級排序。

   9.   Optionally, a |Sec-WebSocket-Extensions| header field, with a
        list of values indicating which extensions the client would like
        to speak.  The interpretation of this header field is discussed
        in Section 9.1.
Sec-WebSocket-Extensions頭字段是可選的,其值是客戶端計劃採用的擴展列表。該字段的解析在9.1中討論。

   10.  Optionally, other header fields, such as those used to send
        cookies or request authentication to a server.  Unknown header
        fields are ignored, as per [RFC2616].
其它字段是可選的,如發送cookies或請求認證等。依照RFC2616不認識的頭字段將被忽略。

4.2.2. Sending the Server’s Opening Handshake
發送server端的握手。

When a client establishes a WebSocket connection to a server, the
server MUST complete the following steps to accept the connection and
send the server’s opening handshake.
當一個客戶端與服務器建立了WebSocket連接後,服務器必須完成以下的步驟,從而接收客戶端請求併發送服務端的握手。

1. If the connection is happening on an HTTPS (HTTP-over-TLS) port,
perform a TLS handshake over the connection. If this fails
(e.g., the client indicated a host name in the extended client
hello "server_name" extension that the server does not host),
then close the connection; otherwise, all further communication
for the connection (including the server’s handshake) MUST run
through the encrypted tunnel [RFC5246].
假如連接建立在https端口之上,在連接上執行了TLS握手。假如失敗(例如客戶端指明的主機名在服務端不存在),則關閉連接;否則該接口上所有的進一步的交互(包括服務端的握手)必須通過加密的通道。
2. The server can perform additional client authentication, for
example, by returning a 401 status code with the corresponding
|WWW-Authenticate| header field as described in [RFC2616].
服務端可以對客戶端進行額外的校驗,例如,可以返回401狀態碼與在RFC2616中描述的WWW-Authenticate的頭字段。

3. The server MAY redirect the client using a 3xx status code
[RFC2616]. Note that this step can happen together with, before,
or after the optional authentication step described above.
服務端可以通過3XX狀態碼對客戶端進行重定向。注意,該步驟可以同上述所說的驗證階段同時、提前或滯後執行。

4. Establish the following information:
構建下述信息:

/origin/
The |Origin| header field in the client’s handshake indicates
the origin of the script establishing the connection. The
origin is serialized to ASCII and converted to lowercase. The
server MAY use this information as part of a determination of
whether to accept the incoming connection. If the server does
not validate the origin, it will accept connections from
anywhere. If the server does not wish to accept this
connection, it MUST return an appropriate HTTP error code
(e.g., 403 Forbidden) and abort the WebSocket handshake
described in this section. For more detail, refer to
Section 10.
客戶端握手中的Origin頭字段代表的是建立連接的腳本的“源”。“源”被序列化成ASCII碼並轉成小寫的。服務端可能會把該元素作爲考慮是否接收接入連接的一個因素。假如服務端不驗證Origin,它可以從任何地方接收連接。假如服務端不期望接收該連接,它必須返回一個適當的HTTP錯誤碼(例如:403拒絕)然後終止本節中描述的WebSocket握手。在第十章中會有更多信息。

/key/
The |Sec-WebSocket-Key| header field in the client’s handshake
includes a base64-encoded value that, if decoded, is 16 bytes
in length. This (encoded) value is used in the creation of
the server’s handshake to indicate an acceptance of the
connection. It is not necessary for the server to base64-
decode the |Sec-WebSocket-Key| value.
客戶端握手中的Sec-WebSocket-Key頭字段包含一個base64編碼的值,解碼後是16位長。創建服務端握手的時候會用到該編碼後的值,代表着接受該連接。服務端不需要去解碼這個值。

/version/
The |Sec-WebSocket-Version| header field in the client’s
handshake includes the version of the WebSocket Protocol with
which the client is attempting to communicate. If this
version does not match a version understood by the server, the
server MUST abort the WebSocket handshake described in this
section and instead send an appropriate HTTP error code (such
as 426 Upgrade Required) and a |Sec-WebSocket-Version| header
field indicating the version(s) the server is capable of
understanding.
客戶端握手中的Sec-WebSocket-Version是客戶端預計進行交互的WebSocket協議的版本。如果這個版本與服務端支持的版本不符,服務端必須終止這個Websocket握手,返回一個合適的http錯誤碼(就像升級需要的426),並且把服務端支持的版本返回去。

/resource name/
An identifier for the service provided by the server. If the
server provides multiple services, then the value should be
derived from the resource name given in the client’s handshake
in the "Request-URI" [RFC2616] of the GET method. If the
requested service is not available, the server MUST send an
appropriate HTTP error code (such as 404 Not Found) and abort
the WebSocket handshake.
服務端提供的服務的標誌。假如服務端提供了多種服務,這個值需要從客戶端握手中的resource name推斷出來。假如要求的服務不可用,服務端必須返回一個適當的錯誤碼(例如404無法找到錯誤)並終止WebSocket握手。

/subprotocol/
Either a single value representing the subprotocol the server
is ready to use or null. The value chosen MUST be derived
from the client’s handshake, specifically by selecting one of
the values from the |Sec-WebSocket-Protocol| field that the
server is willing to use for this connection (if any). If the
client’s handshake did not contain such a header field or if
the server does not agree to any of the client’s requested
subprotocols, the only acceptable value is null. The absence
of such a field is equivalent to the null value (meaning that
if the server does not wish to agree to one of the suggested
subprotocols, it MUST NOT send back a |Sec-WebSocket-Protocol|
header field in its response). The empty string is not the
same as the null value for these purposes and is not a legal
value for this field. The ABNF for the value of this header
field is (token), where the definitions of constructs and
rules are as given in [RFC2616].
或者用一個值表明服務端準備使用的子協議,或者爲null。選中的值必須從客戶端的握手中推斷出來,尤其是從服務端準備在該連接上使用的協議Sec-WebSocket-Protocol中選擇一個。假如客戶端握手中不包含該選項,或者服務端不接受客戶端要求的任何子協議,唯一可以接受的值是null。沒有這個選項等同於null(意思是如果服務端不打算認同任何一個推薦的子協議,那麼在響應的時候必須不返回Sec-WebSocket-Protocol字段)。空字符串不等同於null而且也不是一個合法的取值。該頭字段的ABNF值是(tocken),在[RFC2616中給出了構造定義和規則。


/extensions/
A (possibly empty) list representing the protocol-level
extensions the server is ready to use. If the server supports
multiple extensions, then the value MUST be derived from the
client’s handshake, specifically by selecting one or more of
the values from the |Sec-WebSocket-Extensions| field. The
absence of such a field is equivalent to the null value. The
empty string is not the same as the null value for these
purposes. Extensions not listed by the client MUST NOT be
listed. The method by which these values should be selected
and interpreted is discussed in Section 9.1.
該值標誌服務端準備去使用的協議級別的擴展列表(可能爲空)。假如服務端支持多個擴展,這個值必須從客戶端的握手中推斷出來,尤其是從Sec-WebSocket-Extensions字段中選擇一個或多個值得時候。沒有該字段等同於null。空字符串與null值不等價。客戶端沒有列出的擴展必須不被列出。如何選擇及解讀的方法在9.1節中會進行討論。

5. If the server chooses to accept the incoming connection, it MUST
reply with a valid HTTP response indicating the following.
假如服務端決定接受接入的連接,它必須採用一個合法的HTTP response進行迴應,該response包含以下信息:

1. A Status-Line with a 101 response code as per RFC 2616
[RFC2616]. Such a response could look like "HTTP/1.1 101
Switching Protocols".
按照RFC 2616描述的101響應編碼行。 響應的格式如: "HTTP/1.1 101 Switching Protocols"。

2. An |Upgrade| header field with value "websocket" as per RFC
2616 [RFC2616].
按照RFC 2616描述的Upgrade 頭字段,值是"websocket"。

3. A |Connection| header field with value "Upgrade".
Connection頭字段,值是"Upgrade".

4. A |Sec-WebSocket-Accept| header field. The value of this
header field is constructed by concatenating /key/, defined
above in step 4 in Section 4.2.2, with the string "258EAFA5-
E914-47DA-95CA-C5AB0DC85B11", taking the SHA-1 hash of this
concatenated value to obtain a 20-byte value and base64-
encoding (see Section 4 of [RFC4648]) this 20-byte hash.
Sec-WebSocket-Accept頭字段。連接4.2.2節第四步中定義的key與"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"串,對該串做SHA-1 散列加密後得到一個20位的串,再進行base64編碼得到該字段的值。

The ABNF [RFC2616] of this header field is defined as follows:
這個頭字段的ABNF定義如下:

Sec-WebSocket-Accept = base64-value-non-empty
base64-value-non-empty = (1*base64-data [ base64-padding ]) |
base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") |
(3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"

NOTE: As an example, if the value of the |Sec-WebSocket-Key| header
field in the client’s handshake were "dGhlIHNhbXBsZSBub25jZQ==", the
server would append the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
to form the string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-
C5AB0DC85B11". The server would then take the SHA-1 hash of this
string, giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90
0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value
is then base64-encoded, to give the value
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", which would be returned in the
|Sec-WebSocket-Accept| header field.
注意:舉一個例子,假如客戶端握手Sec-WebSocket-Key頭字段的值是 "dGhlIHNhbXBsZSBub25jZQ==",服務端追加"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"字段形成字符串:"dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"。服務端然後對該串做SHA-1 散列加密,形成0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x900xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea.這個值進行base64編碼,形成"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",最終被當做|Sec-WebSocket-Accept| 頭信息返回給客戶端。

5. Optionally, a |Sec-WebSocket-Protocol| header field, with a
value /subprotocol/ as defined in step 4 in Section 4.2.2.
可選的,Sec-WebSocket-Protocol頭字段以子協議爲值。

6. Optionally, a |Sec-WebSocket-Extensions| header field, with a
value /extensions/ as defined in step 4 in Section 4.2.2. If
multiple extensions are to be used, they can all be listed in
a single |Sec-WebSocket-Extensions| header field or split
between multiple instances of the |Sec-WebSocket-Extensions|
header field.
可選的,Sec-WebSocket-Extensions字段的值是4.2.2節中第四步定義的擴展列表。如果允許多個擴展,它們可以在一個Sec-WebSocket-Extensions中列出,也可以劃分成多個Sec-WebSocket-Extensions字段。

This completes the server’s handshake. If the server finishes these
steps without aborting the WebSocket handshake, the server considers
the WebSocket connection to be established and that the WebSocket
connection is in the OPEN state. At this point, the server may begin
sending (and receiving) data.
到這裏就完成了服務端的握手。假如服務端完成了所有的步驟,沒有終止WebSocket握手,服務端就認爲該WebSocket連接建立成功並處於OPEN狀態。到這,服務端就可以接收發送數據了。

4.3. Collected ABNF for New Header Fields Used in Handshake
收集在握手中使用到的新的頭字段

This section is using ABNF syntax/rules from Section 2.1 of
[RFC2616], including the "implied *LWS rule".
該節使用2.1節中的ABNF語法/規則,包括"implied *LWS rule"。

Note that the following ABNF conventions are used in this section.
Some names of the rules correspond to names of the corresponding
header fields. Such rules express values of the corresponding header
fields, for example, the Sec-WebSocket-Key ABNF rule describes syntax
of the |Sec-WebSocket-Key| header field value. ABNF rules with the
"-Client" suffix in the name are only used in requests sent by the
client to the server; ABNF rules with the "-Server" suffix in the
name are only used in responses sent by the server to the client.
For example, the ABNF rule Sec-WebSocket-Protocol-Client describes
syntax of the |Sec-WebSocket-Protocol| header field value sent by the
client to the server.
注意下面這些ABNF約定,在本節中用到了。一些規則的名稱與一些頭字段的名稱對應。這些規則展示相應的頭字段的值,例如,Sec-WebSocket-Key ABNF規則描述了|Sec-WebSocket-Key|頭字段值得語法。ABNF中以"-Client"最爲後綴的規則僅僅用在從客戶端發往服務端的請求中;ABNF中以”-Server“結尾的規則僅僅用在從服務端發往客戶端的響應中。例如,Sec-WebSocket-Protocol-Client 規則描述了由客戶端發往服務端的Sec-WebSocket-Protocol頭字段的值。

The following new header fields can be sent during the handshake from
the client to the server:
以下的新的頭字段可以在從客戶端發送服務端的握手中發送:
Sec-WebSocket-Key = base64-value-non-empty
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Protocol-Client = 1#token
Sec-WebSocket-Version-Client = version
base64-value-non-empty = (1*base64-data [ base64-padding ]) |
base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") |
(3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"
extension-list = 1#extension
extension = extension-token *( ";" extension-param )
extension-token = registered-token
registered-token = token

extension-param = token [ "=" (token | quoted-string) ]
; When using the quoted-string syntax variant, the value
; after quoted-string unescaping MUST conform to the
; ’token’ ABNF.
NZDIGIT = "1" | "2" | "3" | "4" | "5" | "6" |
"7" | "8" | "9"
version = DIGIT | (NZDIGIT DIGIT) |
("1" DIGIT DIGIT) | ("2" DIGIT DIGIT)
; Limited to 0-255 range, with no leading zeros


The following new header fields can be sent during the handshake from
the server to the client:
以下的新頭字段可以從服務端到客戶端的握手中發送。
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Accept = base64-value-non-empty
Sec-WebSocket-Protocol-Server = token
Sec-WebSocket-Version-Server = 1#version


4.4. Supporting Multiple Versions of WebSocket Protocol
支持多個版本的WebSocket 協議

This section provides some guidance on supporting multiple versions
of the WebSocket Protocol in clients and servers.
本節爲在客戶端和服務端使用多個版本的WebSocket協議提供了一些指導。

Using the WebSocket version advertisement capability (the
|Sec-WebSocket-Version| header field), a client can initially request
the version of the WebSocket Protocol that it prefers (which doesn’t
necessarily have to be the latest supported by the client). If the
server supports the requested version and the handshake message is
otherwise valid, the server will accept that version. If the server
doesn’t support the requested version, it MUST respond with a
|Sec-WebSocket-Version| header field (or multiple
|Sec-WebSocket-Version| header fields) containing all versions it is
willing to use. At this point, if the client supports one of the
advertised versions, it can repeat the WebSocket handshake using a
new version value.
通過WebSocket的版本廣告功能(Sec-WebSocket-Version頭字段),客戶端可以先採用它更期望的WebSocket版本(不一定是客戶端最新支持的版本)進行請求。假如服務端支持請求的版本而且握手信息也有效,服務端將接受那個版本。假如服務端不支持這個版本,它必須通過Sec-WebSocket-Version(或者是多個Sec-WebSocket-Version)進行響應,說明它所支持的所有版本信息。這時,如果客戶端支持建議版本中的一個,它可以使用新版本重複WebSocket握手。

The following example demonstrates version negotiation described
above:
下面的例子展示了上面描述的版本轉換過程:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 25

The response from the server might look as follows:
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13, 8, 7
Note that the last response from the server might also look like:
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13
Sec-WebSocket-Version: 8, 7
The client now repeats the handshake that conforms to version 13:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 13
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章