RFC6455-The WebSocket protocol 之四:Opening Handshake 4.1. Client Requirements

4.Opening Handshake 4.1. Client Requirements
第四章:握手 第一節:客戶端的要求

To _Establish a WebSocket Connection_, a client opens a connection
and sends a handshake as defined in this section. A connection is
defined to initially be in a CONNECTING state. A client will need to
supply a /host/, /port/, /resource name/, and a /secure/ flag, which
are the components of a WebSocket URI as discussed in Section 3,
along with a list of /protocols/ and /extensions/ to be used.
Additionally, if the client is a web browser, it supplies /origin/.

爲了建立一個WebSocket連接,一個客戶端打開連接併發送一個握手,就像本節中定義的。一個連接最初處於“連接中”狀態。一個客戶端需要提供一個/主機名/,/端口號/,/資源名/,一個/安全/標記,這些都是第三章中提到的WebSocket的URI的一部分,後面緊跟着要使用的/協議/和/擴展/的列表。最後,假如客戶端是瀏覽器,還需要提供/源/。

Clients running in controlled environments, e.g., browsers on mobile
handsets tied to specific carriers, MAY offload the management of the
connection to another agent on the network. In such a situation, the
client for the purposes of this specification is considered to
include both the handset software and any such agents.
在受控環境中運行的客戶端,例如綁定到特定運營商的手機,可能把連接的管理權交給網絡上的另外的agent。在這種情況下,本規範中提到的客戶端,即包括手機軟件又包括相關的agent。

When the client is to _Establish a WebSocket Connection_ given a set
of (/host/, /port/, /resource name/, and /secure/ flag), along with a
list of /protocols/ and /extensions/ to be used, and an /origin/ in
the case of web browsers, it MUST open a connection, send an opening
handshake, and read the server’s handshake in response. The exact
requirements of how the connection should be opened, what should be
sent in the opening handshake, and how the server’s response should
be interpreted are as follows in this section. In the following
text, we will use terms from Section 3, such as "/host/" and
"/secure/ flag" as defined in that section.
當客戶端通過提供一組參數:(/host/, /port/, /resource name/, and /secure/ flag),要使用到的協議和擴展,在瀏覽器的情況下還會提供/源/,創建一個WebSocket連接的時候,它必須打開一個連接,發送一個打開的握手,讀取服務器端相應的握手。連接如何被打開、打開握手中應該發送什麼、服務器端的響應如何去解讀,在下面都會進行說明。在下面的內容中,我們將會使用到第三章中定義的"/host/" "/secure/ flag"  術語。

1. The components of the WebSocket URI passed into this algorithm
(/host/, /port/, /resource name/, and /secure/ flag) MUST be
valid according to the specification of WebSocket URIs specified
in Section 3. If any of the components are invalid, the client
MUST _Fail the WebSocket Connection_ and abort these steps.
發送到(/host/, /port/, /resource name/, and /secure/ flag) 算法的WebSocket URI的組件必須同第三章中定義的一樣有效。假如任何組件無效,客戶端需要釋放連接並終止步驟。

2. If the client already has a WebSocket connection to the remote
host (IP address) identified by /host/ and port /port/ pair, even
if the remote host is known by another name, the client MUST wait
until that connection has been established or for that connection
to have failed. There MUST be no more than one connection in a
CONNECTING state. If multiple connections to the same IP address
are attempted simultaneously, the client MUST serialize them so
that there is no more than one connection at a time running
through the following steps.
假如客戶端已經通過(host por t對)與服務器有了連接,縱然服務器有其它的名稱,客戶端必須等待該連接的正式建立或失敗。在這裏,處於連接狀態中的連接必須只有一個。假如與同一個ip地址的多個連接同事到達,客戶端需要對這些連接進行排序,從而保證在執行下面的步驟時,僅有一個連接存在。

If the client cannot determine the IP address of the remote host
(for example, because all communication is being done through a
proxy server that performs DNS queries itself), then the client
MUST assume for the purposes of this step that each host name
refers to a distinct remote host, and instead the client SHOULD
limit the total number of simultaneous pending connections to a
reasonably low number (e.g., the client might allow simultaneous
pending connections to a.example.com and b.example.com, but if
thirty simultaneous connections to a single host are requested,
that may not be allowed). For example, in a web browser context,
the client needs to consider the number of tabs the user has open
in setting a limit to the number of simultaneous pending
connections.
假如客戶端無法確定遠程服務器的ip地址(例如當所有的交互都是通過代理實現時),它必須假設當前步驟中的每一個服務器名稱都指向不同的遠程服務器,並把同時等待連接的連接數限制在一個比較合理的小的數量上(例如,客戶端允許同時等待連接到a.example.com和a.example.com,但是當出現第三個同時連接請求時,是不被允許的)。例如,在瀏覽器中,客戶端需要設置同時打開的tab數量,該設置就是爲了限制同時打開的連接數。

NOTE: This makes it harder for a script to perform a denial-of-
service attack by just opening a large number of WebSocket
connections to a remote host. A server can further reduce the
load on itself when attacked by pausing before closing the
connection, as that will reduce the rate at which the client
reconnects.
注意:這使得通過一個腳本向遠程服務器打開大量的連接的方式進行“拒絕服務攻擊”更困難。當連接關閉前被暫停時,服務器可以進一步減少本身的負載,從而減少客戶端重連的次數。

NOTE: There is no limit to the number of established WebSocket
connections a client can have with a single remote host. Servers
can refuse to accept connections from hosts/IP addresses with an
excessive number of existing connections or disconnect resource-
hogging connections when suffering high load.
注意:一個客戶端與一個遠程服務器的WebSocket連接數是沒有限制的。高負載的情況下存在大量的連接,服務器可以選擇拒絕來自某些ip地址的連接,或者釋放佔用的連接資源。

3. _Proxy Usage_: If the client is configured to use a proxy when
using the WebSocket Protocol to connect to host /host/ and port
/port/, then the client SHOULD connect to that proxy and ask it
to open a TCP connection to the host given by /host/ and the port
given by /port/.
當客戶端採用WebSocket協議連接到遠程服務器時,如果使用代理,客戶端應該連接到代理並讓代理向指定的hot和port建立連接。

EXAMPLE: For example, if the client uses an HTTP proxy for all
traffic, then if it was to try to connect to port 80 on server
example.com, it might send the following lines to the proxy
server:
CONNECT example.com:80 HTTP/1.1
Host: example.com
If there was a password, the connection might look like:
CONNECT example.com:80 HTTP/1.1
Host: example.com
Proxy-authorization: Basic ZWRuYW1vZGU6bm9jYXBlcyE=
示例:當客戶端使用http代理進行傳輸時,假如它要通過80端口連接到server.example.com,它需要把下面的信息發送給代理服務器:
CONNECT example.com:80 HTTP/1.1
Host: example.com
當有密碼時,連接信息如下所示:
CONNECT example.com:80 HTTP/1.1
Host: example.com
Proxy-authorization: Basic ZWRuYW1vZGU6bm9jYXBlcyE=


If the client is not configured to use a proxy, then a direct TCP
connection SHOULD be opened to the host given by /host/ and the
port given by /port/.
假如客戶端沒有設置代理,則需要直接打開一個連接。

NOTE: Implementations that do not expose explicit UI for
selecting a proxy for WebSocket connections separate from other
proxies are encouraged to use a SOCKS5 [RFC1928] proxy for
WebSocket connections, if available, or failing that, to prefer
the proxy configured for HTTPS connections over the proxy
configured for HTTP connections.
與其它代理不同,沒有選擇代理方式的實現更推薦使用SOCKS5 [RFC1928]代理方式,如果可用或者失敗,建立在http 連接代理之上的https 連接代理更受歡迎。

For the purpose of proxy autoconfiguration scripts, the URI to
pass the function MUST be constructed from /host/, /port/,
/resource name/, and the /secure/ flag using the definition of a
WebSocket URI as given in Section 3.
爲了實現能自動配置腳本的代理,用來傳遞函數的URI必須由host、port、resource name、secure標記組成,就像第三章中定義的WebSocket URI。

NOTE: The WebSocket Protocol can be identified in proxy
autoconfiguration scripts from the scheme ("ws" for unencrypted
connections and "wss" for encrypted connections).
注意:可以通過代理自動配置腳本把WebSocket 協議從方案(scheme)中識別出來(“WS”代表未加密的連接,“WSS”代表加密的連接)。


4. If the connection could not be opened, either because a direct
connection failed or because any proxy used returned an error,
then the client MUST _Fail the WebSocket Connection_ and abort
the connection attempt.
假如連接無法打開,或者因爲直接連接失敗,或者因爲採用的代理返回了錯誤,客戶端必須捨棄WebSocket連接並停止連接嘗試。

5. If /secure/ is true, the client MUST perform a TLS handshake over
the connection after opening the connection and before sending
the handshake data [RFC2818]. If this fails (e.g., the server’s
certificate could not be verified), then the client MUST _Fail
the WebSocket Connection_ and abort the connection. Otherwise,
all further communication on this channel MUST run through the
encrypted tunnel [RFC5246].
假如開啓了安全選項,客戶端在打開連接後發送數據前,必須進行TLS握手。假如失敗(例如服務器端的證書無法驗證),客戶端必須捨棄Websocket連接並終止連接。否則,所有進一步的交互都必須在加密通道中進行。

Clients MUST use the Server Name Indication extension in the TLS
handshake [RFC6066].
客戶端必須使用TLS握手中的服務器名稱指示的擴展(Server Name Indication extension)。

Once a connection to the server has been established (including a
connection via a proxy or over a TLS-encrypted tunnel), the client
MUST send an opening handshake to the server. The handshake consists
of an HTTP Upgrade request, along with a list of required and
optional header fields. The requirements for this handshake are as
follows.
一旦通過代理或TLS加密通道與服務器建立了連接,客戶端必須向服務器發送一個打開的握手。該握手由http upgrade請求組成,後面緊跟着一系列必須的頭字段信息。該握手的要求如下:

1. The handshake MUST be a valid HTTP request as specified by
[RFC2616].
該握手必須是一個有效的http請求。

2. The method of the request MUST be GET, and the HTTP version MUST
be at least 1.1.
For example, if the WebSocket URI is "ws://example.com/chat",
the first line sent should be "GET /chat HTTP/1.1".
請求的方法必須是get,http的版本必須在1.1之上。例如,如果websocket uri 是"ws://example.com/chat",發送的第一行應該是 "GET /chat HTTP/1.1".

3. The "Request-URI" part of the request MUST match the /resource
name/ defined in Section 3 (a relative URI) or be an absolute
http/https URI that, when parsed, has a /resource name/, /host/,
and /port/ that match the corresponding ws/wss URI.
請求URI必須與第三章中定義的resource name 匹配或者是一個http/https的絕對URI,轉換後與含有一個/resource name/, /host/,and /port的ws/wss uri匹配。

4. The request MUST contain a |Host| header field whose value
contains /host/ plus optionally ":" followed by /port/ (when not
using the default port).
當沒有采用默認端口時,請求頭必須包含Host字段,該字段包括host:port。

5. The request MUST contain an |Upgrade| header field whose value
MUST include the "websocket" keyword.
請求必須包含頭信息:Upgrade,它的值必須包含"websocket" 關鍵字。

6. The request MUST contain a |Connection| header field whose value
MUST include the "Upgrade" token.
請求必須包含頭信息:Connection,它的值必須包含"Upgrade" 記號。

7. The request MUST include a header field with the name
|Sec-WebSocket-Key|. The value of this header field MUST be a
nonce consisting of a randomly selected 16-byte value that has
been base64-encoded (see Section 4 of [RFC4648]). The nonce
MUST be selected randomly for each connection.
NOTE: As an example, if the randomly selected value was the
sequence of bytes 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, the value of the header
field would be "AQIDBAUGBwgJCgsMDQ4PEC=="
請求必須包含Sec-WebSocket-Key頭信息。該頭信息的值必須是一個nonce ,它由一個隨機的16byte值經過bast64編碼組成。對於每一個連接,nonce 必須是隨機選擇的。例如,如果隨機數的值爲0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x090x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10,則頭信息的值是 "AQIDBAUGBwgJCgsMDQ4PEC=="

8. The request MUST include a header field with the name |Origin|
[RFC6454] if the request is coming from a browser client. If
the connection is from a non-browser client, the request MAY
include this header field if the semantics of that client match
the use-case described here for browser clients. The value of
this header field is the ASCII serialization of origin of the
context in which the code establishing the connection is
running. See [RFC6454] for the details of how this header field
value is constructed.
假如請求來自於瀏覽器,必須包含Origin選項。來自於非瀏覽器的請求,如果客戶端的語意與瀏覽器客戶端中描述的一致,也可以包含這個選項。這個頭字段的值由建立連接的上下文的origin的ascll碼組成。
As an example, if code downloaded from www.example.com attempts
to establish a connection to ww2.example.com, the value of the
header field would be "http://www.example.com".
例如,如果從www.example.com下載的代碼嘗試連接到www.example2.com,頭字段的值是:http://www.example.com。

9. The request MUST include a header field with the name
|Sec-WebSocket-Version|. The value of this header field MUST be
13.
請求必須包含|Sec-WebSocket-Version頭信息,它的值是13.
NOTE: Although draft versions of this document (-09, -10, -11,
and -12) were posted (they were mostly comprised of editorial
changes and clarifications and not changes to the wire
protocol), values 9, 10, 11, and 12 were not used as valid
values for Sec-WebSocket-Version. These values were reserved in
the IANA registry but were not and will not be used.
儘管該文檔的操作版本被髮送,9、10、11、12不作爲Sec-WebSocket-Version合法的值。這些值被保留在IANA 註冊表中,從來以及將來都不會使用。

10. The request MAY include a header field with the name
|Sec-WebSocket-Protocol|. If present, this value indicates one
or more comma-separated subprotocol the client wishes to speak,
ordered by preference. The elements that comprise this value
MUST be non-empty strings with characters in the range U+0021 to
U+007E not including separator characters as defined in
[RFC2616] and MUST all be unique strings. The ABNF for the
value of this header field is 1#token, where the definitions of
constructs and rules are as given in [RFC2616].
請求必須包含|Sec-WebSocket-Protocol頭信息。假如存在的話,它的值是一個或多個通過逗號分隔的客戶端計劃去使用的協議,按照優先級進行排序。組成該頭信息值的內容必須是介於 U+0021 和U+007E之間的非空字符,不包括分隔符,而且必須是唯一的。這個值得ABNF值是1#token,同RFC2616中定義的是一致的。

11. The request MAY include a header field with the name
|Sec-WebSocket-Extensions|. If present, this value indicates
the protocol-level extension(s) the client wishes to speak. The
interpretation and format of this header field is described in
Section 9.1.
請求中可能包含Sec-WebSocket-Extensions頭信息。這個值代表客戶端計劃使用的協議級別擴展信息。該頭信息的解釋和格式在9.1中會詳細說明。

12. The request MAY include any other header fields, for example,
cookies [RFC6265] and/or authentication-related header fields
such as the |Authorization| header field [RFC2616], which are
processed according to documents that define them.
Once the client’s opening handshake has been sent, the client MUST
wait for a response from the server before sending any further data.
The client MUST validate the server’s response as follows:
請求中可以包含任何其它的頭信息,例如cookies、驗證信息等,這些信息按照定義它們的文檔進行處理。一旦客戶端的握手發送,在發送進一步信息前,必須等待來自於服務器的迴應。客戶端必須對服務端的響應進行驗證:

1. If the status code received from the server is not 101, the
client handles the response per HTTP [RFC2616] procedures. In
particular, the client might perform authentication if it
receives a 401 status code; the server might redirect the client
using a 3xx status code (but clients are not required to follow
them), etc. Otherwise, proceed as follows.
假如從服務端獲取的狀態不是101,客戶端在每一個http過程處理響應。特殊情況下,如果客戶端獲取到401狀態,它需要執行驗證;服務器端可能會使用3XX狀態碼重置客戶端等等。否則就採用下述步驟執行。

2. If the response lacks an |Upgrade| header field or the |Upgrade|
header field contains a value that is not an ASCII case-
insensitive match for the value "websocket", the client MUST
_Fail the WebSocket Connection_.
假如響應不包含Upgrade頭信息或者Upgrade頭信息的值與"websocket"的ASCII值不匹配(大小寫不敏感),客戶端必須放棄連接。

3. If the response lacks a |Connection| header field or the
|Connection| header field doesn’t contain a token that is an
ASCII case-insensitive match for the value "Upgrade", the client
MUST _Fail the WebSocket Connection_.
假如響應不包含Connection頭信息或者Connection頭信息的值與"Upgrade"的ASCII值不匹配(大小寫不敏感),客戶端必須放棄連接。

4. If the response lacks a |Sec-WebSocket-Accept| header field or
the |Sec-WebSocket-Accept| contains a value other than the
base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket-
Key| (as a string, not base64-decoded) with the string "258EAFA5-
E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and
trailing whitespace, the client MUST _Fail the WebSocket
Connection_.
假如響應不包含Sec-WebSocket-Accept|頭信息或者Sec-WebSocket-Accept|頭信息的值不是Sec-WebSocket-Key的值與258EAFA5-E914-47DA-95CA-C5AB0DC85B11的組合,客戶端必須放棄連接。

5. If the response includes a |Sec-WebSocket-Extensions| header
field and this header field indicates the use of an extension
that was not present in the client’s handshake (the server has
indicated an extension not requested by the client), the client
MUST _Fail the WebSocket Connection_. (The parsing of this
header field to determine which extensions are requested is
discussed in Section 9.1.)
假如響應包含Sec-WebSocket-Extensions頭信息,它的值在客戶端握手中沒有出現,客戶端必須放棄連接。

6. If the response includes a |Sec-WebSocket-Protocol| header field
and this header field indicates the use of a subprotocol that was
not present in the client’s handshake (the server has indicated a
subprotocol not requested by the client), the client MUST _Fail
the WebSocket Connection_.
假如響應包含Sec-WebSocket-Protocol頭信息,它的值在客戶端握手中沒有出現,客戶端必須放棄連接。

If the server’s response does not conform to the requirements for the
server’s handshake as defined in this section and in Section 4.2.2,
the client MUST _Fail the WebSocket Connection_.
假如響應不滿足本節以及 4.2.2中定義的握手,客戶端必須放棄連接。

Please note that according to [RFC2616], all header field names in
both HTTP requests and HTTP responses are case-insensitive.
If the server’s response is validated as provided for above, it is
said that _The WebSocket Connection is Established_ and that the
WebSocket Connection is in the OPEN state. The _Extensions In Use_
is defined to be a (possibly empty) string, the value of which is
equal to the value of the |Sec-WebSocket-Extensions| header field
supplied by the server’s handshake or the null value if that header
field was not present in the server’s handshake. The _Subprotocol In
Use_ is defined to be the value of the |Sec-WebSocket-Protocol|
header field in the server’s handshake or the null value if that
header field was not present in the server’s handshake.
Additionally, if any header fields in the server’s handshake indicate
that cookies should be set (as defined by [RFC6265]), these cookies
are referred to as _Cookies Set During the Server’s Opening
Handshake_.
請注意所有的http請求和響應中的頭信息都是大小寫不敏感的。假如服務器的響應通過了校驗,websocket連接就建立了並處於OPEN狀態。_Extensions 是一個字符串,與服務器響應中的Sec-WebSocket-Extensions頭信息一致,假如頭信息不包括Sec-WebSocket-Extensions,則_Extensions爲null。_Subprotocol 與服務器響應中的Sec-WebSocket-Protocol|頭信息一致,假如頭信息不包括Sec-WebSocket-Protocol|,則_Subprotocol爲null。另外,如果頭信息中標誌需要設置cookies信息,這些cookies信息需要在服務器打卡握手時進行設置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章