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信息需要在服务器打卡握手时进行设置。

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