Internet Engineering Task Force (IETF)                          I. Fette
Request for Comments: 6455                                  Google, Inc.
Category: Standards Track                                    A. Melnikov
ISSN: 2070-1721                                               Isode Ltd.
                                                           December 2011
        
Internet Engineering Task Force (IETF)                          I. Fette
Request for Comments: 6455                                  Google, Inc.
Category: Standards Track                                    A. Melnikov
ISSN: 2070-1721                                               Isode Ltd.
                                                           December 2011
        

The WebSocket Protocol

WebSocket协议

Abstract

摘要

The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for this is the origin-based security model commonly used by web browsers. The protocol consists of an opening handshake followed by basic message framing, layered over TCP. The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or <iframe>s and long polling).

WebSocket协议允许在受控环境中运行不受信任代码的客户端与选择从该代码进行通信的远程主机之间进行双向通信。用于此目的的安全模型是web浏览器常用的基于源代码的安全模型。该协议包括一个开始的握手,然后是基于TCP的基本消息帧。该技术的目标是为基于浏览器的应用程序提供一种机制,这些应用程序需要与服务器进行双向通信,而不依赖于打开多个HTTP连接(例如,使用XMLHttpRequest或<iframe>s和长轮询)。

Status of This Memo

关于下段备忘

This is an Internet Standards Track document.

这是一份互联网标准跟踪文件。

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 5741.

本文件是互联网工程任务组(IETF)的产品。它代表了IETF社区的共识。它已经接受了公众审查,并已被互联网工程指导小组(IESG)批准出版。有关互联网标准的更多信息,请参见RFC 5741第2节。

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc6455.

有关本文件当前状态、任何勘误表以及如何提供反馈的信息,请访问http://www.rfc-editor.org/info/rfc6455.

Copyright Notice

版权公告

Copyright (c) 2011 IETF Trust and the persons identified as the document authors. All rights reserved.

版权所有(c)2011 IETF信托基金和确定为文件作者的人员。版权所有。

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must

本文件受BCP 78和IETF信托有关IETF文件的法律规定的约束(http://trustee.ietf.org/license-info)自本文件出版之日起生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从该文档中提取的代码组件必须

include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

包括信托法律条款第4.e节中所述的简化BSD许可证文本,且不提供简化BSD许可证中所述的担保。

Table of Contents

目录

   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  4
     1.1.  Background . . . . . . . . . . . . . . . . . . . . . . . .  4
     1.2.  Protocol Overview  . . . . . . . . . . . . . . . . . . . .  5
     1.3.  Opening Handshake  . . . . . . . . . . . . . . . . . . . .  6
     1.4.  Closing Handshake  . . . . . . . . . . . . . . . . . . . .  9
     1.5.  Design Philosophy  . . . . . . . . . . . . . . . . . . . .  9
     1.6.  Security Model . . . . . . . . . . . . . . . . . . . . . . 10
     1.7.  Relationship to TCP and HTTP . . . . . . . . . . . . . . . 11
     1.8.  Establishing a Connection  . . . . . . . . . . . . . . . . 11
     1.9.  Subprotocols Using the WebSocket Protocol  . . . . . . . . 12
   2.  Conformance Requirements . . . . . . . . . . . . . . . . . . . 12
     2.1.  Terminology and Other Conventions  . . . . . . . . . . . . 13
   3.  WebSocket URIs . . . . . . . . . . . . . . . . . . . . . . . . 14
   4.  Opening Handshake  . . . . . . . . . . . . . . . . . . . . . . 14
     4.1.  Client Requirements  . . . . . . . . . . . . . . . . . . . 14
     4.2.  Server-Side Requirements . . . . . . . . . . . . . . . . . 20
       4.2.1.  Reading the Client's Opening Handshake . . . . . . . . 21
       4.2.2.  Sending the Server's Opening Handshake . . . . . . . . 22
     4.3.  Collected ABNF for New Header Fields Used in Handshake . . 25
     4.4.  Supporting Multiple Versions of WebSocket Protocol . . . . 26
   5.  Data Framing . . . . . . . . . . . . . . . . . . . . . . . . . 27
     5.1.  Overview . . . . . . . . . . . . . . . . . . . . . . . . . 27
     5.2.  Base Framing Protocol  . . . . . . . . . . . . . . . . . . 28
     5.3.  Client-to-Server Masking . . . . . . . . . . . . . . . . . 32
     5.4.  Fragmentation  . . . . . . . . . . . . . . . . . . . . . . 33
     5.5.  Control Frames . . . . . . . . . . . . . . . . . . . . . . 36
       5.5.1.  Close  . . . . . . . . . . . . . . . . . . . . . . . . 36
       5.5.2.  Ping . . . . . . . . . . . . . . . . . . . . . . . . . 37
       5.5.3.  Pong . . . . . . . . . . . . . . . . . . . . . . . . . 37
     5.6.  Data Frames  . . . . . . . . . . . . . . . . . . . . . . . 38
     5.7.  Examples . . . . . . . . . . . . . . . . . . . . . . . . . 38
     5.8.  Extensibility  . . . . . . . . . . . . . . . . . . . . . . 39
   6.  Sending and Receiving Data . . . . . . . . . . . . . . . . . . 39
     6.1.  Sending Data . . . . . . . . . . . . . . . . . . . . . . . 39
     6.2.  Receiving Data . . . . . . . . . . . . . . . . . . . . . . 40
   7.  Closing the Connection . . . . . . . . . . . . . . . . . . . . 41
     7.1.  Definitions  . . . . . . . . . . . . . . . . . . . . . . . 41
       7.1.1.  Close the WebSocket Connection . . . . . . . . . . . . 41
       7.1.2.  Start the WebSocket Closing Handshake  . . . . . . . . 42
       7.1.3.  The WebSocket Closing Handshake is Started . . . . . . 42
       7.1.4.  The WebSocket Connection is Closed . . . . . . . . . . 42
       7.1.5.  The WebSocket Connection Close Code  . . . . . . . . . 42
        
   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  4
     1.1.  Background . . . . . . . . . . . . . . . . . . . . . . . .  4
     1.2.  Protocol Overview  . . . . . . . . . . . . . . . . . . . .  5
     1.3.  Opening Handshake  . . . . . . . . . . . . . . . . . . . .  6
     1.4.  Closing Handshake  . . . . . . . . . . . . . . . . . . . .  9
     1.5.  Design Philosophy  . . . . . . . . . . . . . . . . . . . .  9
     1.6.  Security Model . . . . . . . . . . . . . . . . . . . . . . 10
     1.7.  Relationship to TCP and HTTP . . . . . . . . . . . . . . . 11
     1.8.  Establishing a Connection  . . . . . . . . . . . . . . . . 11
     1.9.  Subprotocols Using the WebSocket Protocol  . . . . . . . . 12
   2.  Conformance Requirements . . . . . . . . . . . . . . . . . . . 12
     2.1.  Terminology and Other Conventions  . . . . . . . . . . . . 13
   3.  WebSocket URIs . . . . . . . . . . . . . . . . . . . . . . . . 14
   4.  Opening Handshake  . . . . . . . . . . . . . . . . . . . . . . 14
     4.1.  Client Requirements  . . . . . . . . . . . . . . . . . . . 14
     4.2.  Server-Side Requirements . . . . . . . . . . . . . . . . . 20
       4.2.1.  Reading the Client's Opening Handshake . . . . . . . . 21
       4.2.2.  Sending the Server's Opening Handshake . . . . . . . . 22
     4.3.  Collected ABNF for New Header Fields Used in Handshake . . 25
     4.4.  Supporting Multiple Versions of WebSocket Protocol . . . . 26
   5.  Data Framing . . . . . . . . . . . . . . . . . . . . . . . . . 27
     5.1.  Overview . . . . . . . . . . . . . . . . . . . . . . . . . 27
     5.2.  Base Framing Protocol  . . . . . . . . . . . . . . . . . . 28
     5.3.  Client-to-Server Masking . . . . . . . . . . . . . . . . . 32
     5.4.  Fragmentation  . . . . . . . . . . . . . . . . . . . . . . 33
     5.5.  Control Frames . . . . . . . . . . . . . . . . . . . . . . 36
       5.5.1.  Close  . . . . . . . . . . . . . . . . . . . . . . . . 36
       5.5.2.  Ping . . . . . . . . . . . . . . . . . . . . . . . . . 37
       5.5.3.  Pong . . . . . . . . . . . . . . . . . . . . . . . . . 37
     5.6.  Data Frames  . . . . . . . . . . . . . . . . . . . . . . . 38
     5.7.  Examples . . . . . . . . . . . . . . . . . . . . . . . . . 38
     5.8.  Extensibility  . . . . . . . . . . . . . . . . . . . . . . 39
   6.  Sending and Receiving Data . . . . . . . . . . . . . . . . . . 39
     6.1.  Sending Data . . . . . . . . . . . . . . . . . . . . . . . 39
     6.2.  Receiving Data . . . . . . . . . . . . . . . . . . . . . . 40
   7.  Closing the Connection . . . . . . . . . . . . . . . . . . . . 41
     7.1.  Definitions  . . . . . . . . . . . . . . . . . . . . . . . 41
       7.1.1.  Close the WebSocket Connection . . . . . . . . . . . . 41
       7.1.2.  Start the WebSocket Closing Handshake  . . . . . . . . 42
       7.1.3.  The WebSocket Closing Handshake is Started . . . . . . 42
       7.1.4.  The WebSocket Connection is Closed . . . . . . . . . . 42
       7.1.5.  The WebSocket Connection Close Code  . . . . . . . . . 42
        
       7.1.6.  The WebSocket Connection Close Reason  . . . . . . . . 43
       7.1.7.  Fail the WebSocket Connection  . . . . . . . . . . . . 43
     7.2.  Abnormal Closures  . . . . . . . . . . . . . . . . . . . . 44
       7.2.1.  Client-Initiated Closure . . . . . . . . . . . . . . . 44
       7.2.2.  Server-Initiated Closure . . . . . . . . . . . . . . . 44
       7.2.3.  Recovering from Abnormal Closure . . . . . . . . . . . 44
     7.3.  Normal Closure of Connections  . . . . . . . . . . . . . . 45
     7.4.  Status Codes . . . . . . . . . . . . . . . . . . . . . . . 45
       7.4.1.  Defined Status Codes . . . . . . . . . . . . . . . . . 45
       7.4.2.  Reserved Status Code Ranges  . . . . . . . . . . . . . 47
   8.  Error Handling . . . . . . . . . . . . . . . . . . . . . . . . 48
     8.1.  Handling Errors in UTF-8-Encoded Data  . . . . . . . . . . 48
   9.  Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . 48
     9.1.  Negotiating Extensions . . . . . . . . . . . . . . . . . . 48
     9.2.  Known Extensions . . . . . . . . . . . . . . . . . . . . . 50
   10. Security Considerations  . . . . . . . . . . . . . . . . . . . 50
     10.1. Non-Browser Clients  . . . . . . . . . . . . . . . . . . . 50
     10.2. Origin Considerations  . . . . . . . . . . . . . . . . . . 50
     10.3. Attacks On Infrastructure (Masking)  . . . . . . . . . . . 51
     10.4. Implementation-Specific Limits . . . . . . . . . . . . . . 52
     10.5. WebSocket Client Authentication  . . . . . . . . . . . . . 53
     10.6. Connection Confidentiality and Integrity . . . . . . . . . 53
     10.7. Handling of Invalid Data . . . . . . . . . . . . . . . . . 53
     10.8. Use of SHA-1 by the WebSocket Handshake  . . . . . . . . . 54
   11. IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 54
     11.1. Registration of New URI Schemes  . . . . . . . . . . . . . 54
       11.1.1. Registration of "ws" Scheme  . . . . . . . . . . . . . 54
       11.1.2. Registration of "wss" Scheme . . . . . . . . . . . . . 55
     11.2. Registration of the "WebSocket" HTTP Upgrade Keyword . . . 56
     11.3. Registration of New HTTP Header Fields . . . . . . . . . . 57
       11.3.1. Sec-WebSocket-Key  . . . . . . . . . . . . . . . . . . 57
       11.3.2. Sec-WebSocket-Extensions . . . . . . . . . . . . . . . 58
       11.3.3. Sec-WebSocket-Accept . . . . . . . . . . . . . . . . . 58
       11.3.4. Sec-WebSocket-Protocol . . . . . . . . . . . . . . . . 59
       11.3.5. Sec-WebSocket-Version  . . . . . . . . . . . . . . . . 60
     11.4. WebSocket Extension Name Registry  . . . . . . . . . . . . 61
     11.5. WebSocket Subprotocol Name Registry  . . . . . . . . . . . 61
     11.6. WebSocket Version Number Registry  . . . . . . . . . . . . 62
     11.7. WebSocket Close Code Number Registry . . . . . . . . . . . 64
     11.8. WebSocket Opcode Registry  . . . . . . . . . . . . . . . . 65
     11.9. WebSocket Framing Header Bits Registry . . . . . . . . . . 66
   12. Using the WebSocket Protocol from Other Specifications . . . . 66
   13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 67
   14. References . . . . . . . . . . . . . . . . . . . . . . . . . . 68
     14.1. Normative References . . . . . . . . . . . . . . . . . . . 68
     14.2. Informative References . . . . . . . . . . . . . . . . . . 69
        
       7.1.6.  The WebSocket Connection Close Reason  . . . . . . . . 43
       7.1.7.  Fail the WebSocket Connection  . . . . . . . . . . . . 43
     7.2.  Abnormal Closures  . . . . . . . . . . . . . . . . . . . . 44
       7.2.1.  Client-Initiated Closure . . . . . . . . . . . . . . . 44
       7.2.2.  Server-Initiated Closure . . . . . . . . . . . . . . . 44
       7.2.3.  Recovering from Abnormal Closure . . . . . . . . . . . 44
     7.3.  Normal Closure of Connections  . . . . . . . . . . . . . . 45
     7.4.  Status Codes . . . . . . . . . . . . . . . . . . . . . . . 45
       7.4.1.  Defined Status Codes . . . . . . . . . . . . . . . . . 45
       7.4.2.  Reserved Status Code Ranges  . . . . . . . . . . . . . 47
   8.  Error Handling . . . . . . . . . . . . . . . . . . . . . . . . 48
     8.1.  Handling Errors in UTF-8-Encoded Data  . . . . . . . . . . 48
   9.  Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . 48
     9.1.  Negotiating Extensions . . . . . . . . . . . . . . . . . . 48
     9.2.  Known Extensions . . . . . . . . . . . . . . . . . . . . . 50
   10. Security Considerations  . . . . . . . . . . . . . . . . . . . 50
     10.1. Non-Browser Clients  . . . . . . . . . . . . . . . . . . . 50
     10.2. Origin Considerations  . . . . . . . . . . . . . . . . . . 50
     10.3. Attacks On Infrastructure (Masking)  . . . . . . . . . . . 51
     10.4. Implementation-Specific Limits . . . . . . . . . . . . . . 52
     10.5. WebSocket Client Authentication  . . . . . . . . . . . . . 53
     10.6. Connection Confidentiality and Integrity . . . . . . . . . 53
     10.7. Handling of Invalid Data . . . . . . . . . . . . . . . . . 53
     10.8. Use of SHA-1 by the WebSocket Handshake  . . . . . . . . . 54
   11. IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 54
     11.1. Registration of New URI Schemes  . . . . . . . . . . . . . 54
       11.1.1. Registration of "ws" Scheme  . . . . . . . . . . . . . 54
       11.1.2. Registration of "wss" Scheme . . . . . . . . . . . . . 55
     11.2. Registration of the "WebSocket" HTTP Upgrade Keyword . . . 56
     11.3. Registration of New HTTP Header Fields . . . . . . . . . . 57
       11.3.1. Sec-WebSocket-Key  . . . . . . . . . . . . . . . . . . 57
       11.3.2. Sec-WebSocket-Extensions . . . . . . . . . . . . . . . 58
       11.3.3. Sec-WebSocket-Accept . . . . . . . . . . . . . . . . . 58
       11.3.4. Sec-WebSocket-Protocol . . . . . . . . . . . . . . . . 59
       11.3.5. Sec-WebSocket-Version  . . . . . . . . . . . . . . . . 60
     11.4. WebSocket Extension Name Registry  . . . . . . . . . . . . 61
     11.5. WebSocket Subprotocol Name Registry  . . . . . . . . . . . 61
     11.6. WebSocket Version Number Registry  . . . . . . . . . . . . 62
     11.7. WebSocket Close Code Number Registry . . . . . . . . . . . 64
     11.8. WebSocket Opcode Registry  . . . . . . . . . . . . . . . . 65
     11.9. WebSocket Framing Header Bits Registry . . . . . . . . . . 66
   12. Using the WebSocket Protocol from Other Specifications . . . . 66
   13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 67
   14. References . . . . . . . . . . . . . . . . . . . . . . . . . . 68
     14.1. Normative References . . . . . . . . . . . . . . . . . . . 68
     14.2. Informative References . . . . . . . . . . . . . . . . . . 69
        
1. Introduction
1. 介绍
1.1. Background
1.1. 出身背景

_This section is non-normative._

_本节是非规范性的_

Historically, creating web applications that need bidirectional communication between a client and a server (e.g., instant messaging and gaming applications) has required an abuse of HTTP to poll the server for updates while sending upstream notifications as distinct HTTP calls [RFC6202].

历史上,创建需要客户端和服务器之间双向通信的web应用程序(例如,即时消息和游戏应用程序)需要滥用HTTP来轮询服务器以获取更新,同时将上游通知作为不同的HTTP调用发送[RFC6202]。

This results in a variety of problems:

这会导致各种问题:

o The server is forced to use a number of different underlying TCP connections for each client: one for sending information to the client and a new one for each incoming message.

o 服务器被迫为每个客户端使用许多不同的底层TCP连接:一个用于向客户端发送信息,另一个用于每个传入消息。

o The wire protocol has a high overhead, with each client-to-server message having an HTTP header.

o wire协议有很高的开销,每个客户端到服务器的消息都有一个HTTP头。

o The client-side script is forced to maintain a mapping from the outgoing connections to the incoming connection to track replies.

o 客户端脚本被迫维护从传出连接到传入连接的映射,以跟踪回复。

A simpler solution would be to use a single TCP connection for traffic in both directions. This is what the WebSocket Protocol provides. Combined with the WebSocket API [WSAPI], it provides an alternative to HTTP polling for two-way communication from a web page to a remote server.

一个更简单的解决方案是在两个方向上使用单个TCP连接进行通信。这是WebSocket协议提供的。结合WebSocket API[WSAPI],它为从网页到远程服务器的双向通信提供了HTTP轮询的替代方案。

The same technique can be used for a variety of web applications: games, stock tickers, multiuser applications with simultaneous editing, user interfaces exposing server-side services in real time, etc.

同样的技术也可用于各种web应用程序:游戏、股票行情、同时编辑的多用户应用程序、实时公开服务器端服务的用户界面等。

The WebSocket Protocol is designed to supersede existing bidirectional communication technologies that use HTTP as a transport layer to benefit from existing infrastructure (proxies, filtering, authentication). Such technologies were implemented as trade-offs between efficiency and reliability because HTTP was not initially meant to be used for bidirectional communication (see [RFC6202] for further discussion). The WebSocket Protocol attempts to address the goals of existing bidirectional HTTP technologies in the context of the existing HTTP infrastructure; as such, it is designed to work over HTTP ports 80 and 443 as well as to support HTTP proxies and intermediaries, even if this implies some complexity specific to the current environment. However, the design does not limit WebSocket to HTTP, and future implementations could use a simpler handshake over a

WebSocket协议旨在取代现有的双向通信技术,这些技术将HTTP用作传输层,以从现有的基础设施(代理、过滤、身份验证)中获益。这些技术是作为效率和可靠性之间的权衡来实现的,因为HTTP最初并不打算用于双向通信(进一步讨论请参见[RFC6202])。WebSocket协议试图在现有HTTP基础设施的上下文中实现现有双向HTTP技术的目标;因此,它被设计为在HTTP端口80和443上工作,并支持HTTP代理和中介,即使这意味着当前环境特有的复杂性。然而,该设计并没有将WebSocket限制为HTTP,未来的实现可以使用更简单的通过HTTP的握手

dedicated port without reinventing the entire protocol. This last point is important because the traffic patterns of interactive messaging do not closely match standard HTTP traffic and can induce unusual loads on some components.

专用端口,无需重新设计整个协议。最后一点很重要,因为交互消息传递的流量模式与标准HTTP流量不匹配,并且可能会在某些组件上导致异常负载。

1.2. Protocol Overview
1.2. 协议概述

_This section is non-normative._

_本节是非规范性的_

The protocol has two parts: a handshake and the data transfer.

协议分为两部分:握手和数据传输。

The handshake from the client looks as follows:

来自客户端的握手如下所示:

        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
        
        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
        

The handshake from the server looks as follows:

来自服务器的握手如下所示:

        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat
        
        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat
        

The leading line from the client follows the Request-Line format. The leading line from the server follows the Status-Line format. The Request-Line and Status-Line productions are defined in [RFC2616].

客户端的前导行遵循请求行格式。服务器的前导行遵循状态行格式。[RFC2616]中定义了请求行和状态行产品。

An unordered set of header fields comes after the leading line in both cases. The meaning of these header fields is specified in Section 4 of this document. Additional header fields may also be present, such as cookies [RFC6265]. The format and parsing of headers is as defined in [RFC2616].

在这两种情况下,标题字段的无序集都位于前导行之后。本文件第4节规定了这些标题字段的含义。还可能存在其他标头字段,例如Cookie[RFC6265]。标题的格式和解析如[RFC2616]中所定义。

Once the client and server have both sent their handshakes, and if the handshake was successful, then the data transfer part starts. This is a two-way communication channel where each side can, independently from the other, send data at will.

一旦客户端和服务器都发送了握手,如果握手成功,则数据传输部分开始。这是一个双向通信信道,其中每一方可以独立于另一方随意发送数据。

After a successful handshake, clients and servers transfer data back and forth in conceptual units referred to in this specification as "messages". On the wire, a message is composed of one or more

成功握手后,客户端和服务器以本规范中称为“消息”的概念单元来回传输数据。在网络上,一条消息由一条或多条消息组成

frames. The WebSocket message does not necessarily correspond to a particular network layer framing, as a fragmented message may be coalesced or split by an intermediary.

框架。WebSocket消息不一定对应于特定的网络层帧,因为分段消息可能由中间层合并或拆分。

A frame has an associated type. Each frame belonging to the same message contains the same type of data. Broadly speaking, there are types for textual data (which is interpreted as UTF-8 [RFC3629] text), binary data (whose interpretation is left up to the application), and control frames (which are not intended to carry data for the application but instead for protocol-level signaling, such as to signal that the connection should be closed). This version of the protocol defines six frame types and leaves ten reserved for future use.

框架具有关联的类型。属于同一消息的每个帧包含相同类型的数据。广义地说,有文本数据(被解释为UTF-8[RFC3629]文本)、二进制数据(其解释由应用程序决定)和控制帧(其目的不是为应用程序传输数据,而是为协议级信令,例如发送连接应关闭的信号)的类型。此版本的协议定义了六种帧类型,并保留了十种供将来使用。

1.3. Opening Handshake
1.3. 开场握手

_This section is non-normative._

_本节是非规范性的_

The opening handshake is intended to be compatible with HTTP-based server-side software and intermediaries, so that a single port can be used by both HTTP clients talking to that server and WebSocket clients talking to that server. To this end, the WebSocket client's handshake is an HTTP Upgrade request:

开放式握手旨在与基于HTTP的服务器端软件和中介体兼容,以便与该服务器通信的HTTP客户端和与该服务器通信的WebSocket客户端都可以使用单个端口。为此,WebSocket客户端的握手是一个HTTP升级请求:

        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
        
        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
        

In compliance with [RFC2616], header fields in the handshake may be sent by the client in any order, so the order in which different header fields are received is not significant.

根据[RFC2616],握手中的报头字段可以由客户端以任何顺序发送,因此不同报头字段的接收顺序并不重要。

The "Request-URI" of the GET method [RFC2616] is used to identify the endpoint of the WebSocket connection, both to allow multiple domains to be served from one IP address and to allow multiple WebSocket endpoints to be served by a single server.

GET方法[RFC2616]的“请求URI”用于标识WebSocket连接的端点,既允许从一个IP地址为多个域提供服务,也允许单个服务器为多个WebSocket端点提供服务。

The client includes the hostname in the |Host| header field of its handshake as per [RFC2616], so that both the client and the server can verify that they agree on which host is in use.

根据[RFC2616],客户机在其握手的|主机|头字段中包含主机名,以便客户机和服务器都可以验证他们是否同意使用哪个主机。

Additional header fields are used to select options in the WebSocket Protocol. Typical options available in this version are the subprotocol selector (|Sec-WebSocket-Protocol|), list of extensions support by the client (|Sec-WebSocket-Extensions|), |Origin| header field, etc. The |Sec-WebSocket-Protocol| request-header field can be used to indicate what subprotocols (application-level protocols layered over the WebSocket Protocol) are acceptable to the client. The server selects one or none of the acceptable protocols and echoes that value in its handshake to indicate that it has selected that protocol.

附加的标题字段用于选择WebSocket协议中的选项。此版本中可用的典型选项有subtocol选择器(| Sec WebSocket Protocol |)、客户端支持的扩展列表(| Sec WebSocket extensions |)和| Origin | header字段等。| Sec WebSocket Protocol | request header字段可用于指示哪些subtocol(在WebSocket协议上分层的应用程序级协议)是客户端可接受的。服务器选择一个或任何一个可接受的协议,并在其握手中回显该值,以指示它已选择该协议。

Sec-WebSocket-Protocol: chat

Sec WebSocket协议:聊天

The |Origin| header field [RFC6454] is used to protect against unauthorized cross-origin use of a WebSocket server by scripts using the WebSocket API in a web browser. The server is informed of the script origin generating the WebSocket connection request. If the server does not wish to accept connections from this origin, it can choose to reject the connection by sending an appropriate HTTP error code. This header field is sent by browser clients; for non-browser clients, this header field may be sent if it makes sense in the context of those clients.

| Origin | header字段[RFC6454]用于防止脚本在web浏览器中使用WebSocket API对WebSocket服务器进行未经授权的跨源使用。服务器被告知生成WebSocket连接请求的脚本源。如果服务器不希望接受来自此来源的连接,则可以通过发送适当的HTTP错误代码来选择拒绝连接。此标头字段由浏览器客户端发送;对于非浏览器客户端,如果在这些客户端的上下文中有意义,则可以发送此标头字段。

Finally, the server has to prove to the client that it received the client's WebSocket handshake, so that the server doesn't accept connections that are not WebSocket connections. This prevents an attacker from tricking a WebSocket server by sending it carefully crafted packets using XMLHttpRequest [XMLHttpRequest] or a form submission.

最后,服务器必须向客户端证明它收到了客户端的WebSocket握手,以便服务器不接受非WebSocket连接的连接。这可以防止攻击者通过使用XMLHttpRequest[XMLHttpRequest]或表单提交发送精心编制的数据包来欺骗WebSocket服务器。

To prove that the handshake was received, the server has to take two pieces of information and combine them to form a response. The first piece of information comes from the |Sec-WebSocket-Key| header field in the client handshake:

为了证明收到了握手,服务器必须获取两条信息并将它们组合起来形成响应。第一条信息来自客户端握手中的| Sec WebSocket Key | header字段:

        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
        
        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
        

For this header field, the server has to take the value (as present in the header field, e.g., the base64-encoded [RFC4648] version minus any leading and trailing whitespace) and concatenate this with the Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" in string form, which is unlikely to be used by network endpoints that do not understand the WebSocket Protocol. A SHA-1 hash (160 bits) [FIPS.180-3], base64-encoded (see Section 4 of [RFC4648]), of this concatenation is then returned in the server's handshake.

对于此标头字段,服务器必须获取值(如标头字段中存在的值,例如base64编码的[RFC4648]版本减去任何前导和尾随空格),并将其与字符串形式的全局唯一标识符(GUID,[RFC4122])“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”连接起来,不理解WebSocket协议的网络终结点不太可能使用它。然后在服务器的握手中返回该串联的SHA-1哈希(160位)[FIPS.180-3],base64编码(参见[RFC4648]第4节)。

Concretely, if as in the example above, the |Sec-WebSocket-Key| header field had the value "dGhlIHNhbXBsZSBub25jZQ==", the server would concatenate 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, 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 (see Section 4 of [RFC4648]), to give the value "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=". This value would then be echoed in the |Sec-WebSocket-Accept| header field.

具体地说,如果如上例所示,| Sec WebSocket Key | header字段的值为“DGHLIHNHBXBSSBUB25JZQ==”,服务器将连接字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”以形成字符串“DGHLIHNHBXBSSBUB25JZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。然后,服务器将获取该文件的SHA-1散列,给出值0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea。然后对该值进行base64编码(参见[RFC4648]的第4节),以给出值“S3pplmBitxaq9KYGZHZRBK+xOo=”。然后,该值将在| Sec WebSocket Accept |头字段中回显。

The handshake from the server is much simpler than the client handshake. The first line is an HTTP Status-Line, with the status code 101:

来自服务器的握手比客户端的握手简单得多。第一行是HTTP状态行,状态代码为101:

HTTP/1.1 101 Switching Protocols

HTTP/1.1 101交换协议

Any status code other than 101 indicates that the WebSocket handshake has not completed and that the semantics of HTTP still apply. The headers follow the status code.

101以外的任何状态代码都表示WebSocket握手尚未完成,HTTP的语义仍然适用。标题跟随状态代码。

The |Connection| and |Upgrade| header fields complete the HTTP Upgrade. The |Sec-WebSocket-Accept| header field indicates whether the server is willing to accept the connection. If present, this header field must include a hash of the client's nonce sent in |Sec-WebSocket-Key| along with a predefined GUID. Any other value must not be interpreted as an acceptance of the connection by the server.

| Connection |和| Upgrade |头字段完成HTTP升级。| Sec WebSocket Accept |头字段指示服务器是否愿意接受连接。如果存在,则此标头字段必须包含在| Sec WebSocket Key |中发送的客户端nonce的哈希以及预定义的GUID。任何其他值都不能解释为服务器接受连接。

        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        
        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        

These fields are checked by the WebSocket client for scripted pages. If the |Sec-WebSocket-Accept| value does not match the expected value, if the header field is missing, or if the HTTP status code is not 101, the connection will not be established, and WebSocket frames will not be sent.

这些字段由WebSocket客户端检查脚本页面。如果| Sec WebSocket Accept |值与预期值不匹配,如果缺少标头字段,或者如果HTTP状态代码不是101,则不会建立连接,也不会发送WebSocket帧。

Option fields can also be included. In this version of the protocol, the main option field is |Sec-WebSocket-Protocol|, which indicates the subprotocol that the server has selected. WebSocket clients verify that the server included one of the values that was specified in the WebSocket client's handshake. A server that speaks multiple subprotocols has to make sure it selects one based on the client's handshake and specifies it in its handshake.

也可以包括选项字段。在此版本的协议中,主选项字段为| Sec WebSocket protocol |,表示服务器已选择的子协议。WebSocket客户端验证服务器是否包含WebSocket客户端握手中指定的值之一。讲多个子脚本的服务器必须确保根据客户端的握手选择一个子脚本,并在握手中指定它。

Sec-WebSocket-Protocol: chat

Sec WebSocket协议:聊天

The server can also set cookie-related option fields to _set_ cookies, as described in [RFC6265].

服务器还可以将与cookie相关的选项字段设置为_set _cookies,如[RFC6265]中所述。

1.4. Closing Handshake
1.4. 结束握手

_This section is non-normative._

_本节是非规范性的_

The closing handshake is far simpler than the opening handshake.

结束握手比开始握手简单得多。

Either peer can send a control frame with data containing a specified control sequence to begin the closing handshake (detailed in Section 5.5.1). Upon receiving such a frame, the other peer sends a Close frame in response, if it hasn't already sent one. Upon receiving _that_ control frame, the first peer then closes the connection, safe in the knowledge that no further data is forthcoming.

任何一个对等方都可以发送包含指定控制序列数据的控制帧,以开始结束握手(详见第5.5.1节)。在接收到这样一个帧后,另一个对等方发送一个闭合帧作为响应,如果它还没有发送一个闭合帧的话。在接收到该控制帧后,第一个对等方关闭连接,安全地知道没有进一步的数据。

After sending a control frame indicating the connection should be closed, a peer does not send any further data; after receiving a control frame indicating the connection should be closed, a peer discards any further data received.

在发送指示连接应关闭的控制帧后,对等方不发送任何进一步的数据;在接收到指示应关闭连接的控制帧后,对等方将丢弃接收到的任何进一步数据。

It is safe for both peers to initiate this handshake simultaneously.

两个对等方同时发起此握手是安全的。

The closing handshake is intended to complement the TCP closing handshake (FIN/ACK), on the basis that the TCP closing handshake is not always reliable end-to-end, especially in the presence of intercepting proxies and other intermediaries.

结束握手旨在补充TCP结束握手(FIN/ACK),因为TCP结束握手并不总是端到端可靠,尤其是在存在拦截代理和其他中介的情况下。

By sending a Close frame and waiting for a Close frame in response, certain cases are avoided where data may be unnecessarily lost. For instance, on some platforms, if a socket is closed with data in the receive queue, a RST packet is sent, which will then cause recv() to fail for the party that received the RST, even if there was data waiting to be read.

通过发送关闭帧并等待关闭帧响应,可以避免数据可能不必要地丢失的某些情况。例如,在某些平台上,如果使用接收队列中的数据关闭套接字,则发送RST数据包,这将导致接收RST的一方recv()失败,即使有数据等待读取。

1.5. Design Philosophy
1.5. 设计理念

_This section is non-normative._

_本节是非规范性的_

The WebSocket Protocol is designed on the principle that there should be minimal framing (the only framing that exists is to make the protocol frame-based instead of stream-based and to support a distinction between Unicode text and binary frames). It is expected that metadata would be layered on top of WebSocket by the application

WebSocket协议的设计原则是应该有最小的帧(唯一存在的帧是基于协议帧而不是基于流,并且支持Unicode文本和二进制帧之间的区别)。预计应用程序会将元数据分层到WebSocket之上

layer, in the same way that metadata is layered on top of TCP by the application layer (e.g., HTTP).

层,与应用层(例如HTTP)将元数据分层到TCP之上的方式相同。

Conceptually, WebSocket is really just a layer on top of TCP that does the following:

从概念上讲,WebSocket实际上只是TCP之上的一个层,它执行以下操作:

o adds a web origin-based security model for browsers

o 为浏览器添加基于web源的安全模型

o adds an addressing and protocol naming mechanism to support multiple services on one port and multiple host names on one IP address

o 添加寻址和协议命名机制,以支持一个端口上的多个服务和一个IP地址上的多个主机名

o layers a framing mechanism on top of TCP to get back to the IP packet mechanism that TCP is built on, but without length limits

o 在TCP上分层一个帧机制,以返回到TCP构建的IP数据包机制,但不受长度限制

o includes an additional closing handshake in-band that is designed to work in the presence of proxies and other intermediaries

o 包括额外的带内结束握手,设计用于在代理和其他中间人在场的情况下工作

Other than that, WebSocket adds nothing. Basically it is intended to be as close to just exposing raw TCP to script as possible given the constraints of the Web. It's also designed in such a way that its servers can share a port with HTTP servers, by having its handshake be a valid HTTP Upgrade request. One could conceptually use other protocols to establish client-server messaging, but the intent of WebSockets is to provide a relatively simple protocol that can coexist with HTTP and deployed HTTP infrastructure (such as proxies) and that is as close to TCP as is safe for use with such infrastructure given security considerations, with targeted additions to simplify usage and keep simple things simple (such as the addition of message semantics).

除此之外,WebSocket没有添加任何内容。基本上,考虑到Web的限制,它的目的是尽可能地将原始TCP暴露给脚本。它的设计也使得它的服务器可以通过一个有效的HTTP升级请求来与HTTP服务器共享一个端口。从概念上讲,可以使用其他协议来建立客户机-服务器消息传递,但WebSockets的目的是提供一个相对简单的协议,该协议可以与HTTP和部署的HTTP基础设施(如代理)共存,并且在考虑到安全性的情况下,与TCP尽可能接近,以便与此类基础设施一起安全使用,通过有针对性的添加来简化使用并使简单的事情保持简单(例如添加消息语义)。

The protocol is intended to be extensible; future versions will likely introduce additional concepts such as multiplexing.

该协议旨在可扩展;未来的版本可能会引入其他概念,如多路复用。

1.6. Security Model
1.6. 安全模型

_This section is non-normative._

_本节是非规范性的_

The WebSocket Protocol uses the origin model used by web browsers to restrict which web pages can contact a WebSocket server when the WebSocket Protocol is used from a web page. Naturally, when the WebSocket Protocol is used by a dedicated client directly (i.e., not from a web page through a web browser), the origin model is not useful, as the client can provide any arbitrary origin string.

当从网页使用WebSocket协议时,WebSocket协议使用web浏览器使用的源模型来限制哪些网页可以联系WebSocket服务器。当然,当专用客户机直接使用WebSocket协议时(即,不是通过web浏览器从网页中使用),源模型没有用处,因为客户机可以提供任意的源字符串。

This protocol is intended to fail to establish a connection with servers of pre-existing protocols like SMTP [RFC5321] and HTTP, while allowing HTTP servers to opt-in to supporting this protocol if

此协议旨在无法与SMTP[RFC5321]和HTTP等现有协议的服务器建立连接,同时允许HTTP服务器在以下情况下选择支持此协议:

desired. This is achieved by having a strict and elaborate handshake and by limiting the data that can be inserted into the connection before the handshake is finished (thus limiting how much the server can be influenced).

渴望的这是通过进行严格而精细的握手以及在握手完成之前限制可以插入连接中的数据(从而限制对服务器的影响程度)来实现的。

It is similarly intended to fail to establish a connection when data from other protocols, especially HTTP, is sent to a WebSocket server, for example, as might happen if an HTML "form" were submitted to a WebSocket server. This is primarily achieved by requiring that the server prove that it read the handshake, which it can only do if the handshake contains the appropriate parts, which can only be sent by a WebSocket client. In particular, at the time of writing of this specification, fields starting with |Sec-| cannot be set by an attacker from a web browser using only HTML and JavaScript APIs such as XMLHttpRequest [XMLHttpRequest].

类似地,当来自其他协议(尤其是HTTP)的数据发送到WebSocket服务器时,无法建立连接,例如,如果HTML“表单”提交到WebSocket服务器,可能会发生这种情况。这主要是通过要求服务器证明它读取了握手来实现的,只有当握手包含适当的部分时,服务器才能这样做,而这些部分只能由WebSocket客户端发送。特别是,在编写本规范时,攻击者不能仅使用HTML和JavaScript API(如XMLHttpRequest[XMLHttpRequest])从web浏览器设置以| Sec-|开头的字段。

1.7. Relationship to TCP and HTTP
1.7. 与TCP和HTTP的关系

_This section is non-normative._

_本节是非规范性的_

The WebSocket Protocol is an independent TCP-based protocol. Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request.

WebSocket协议是一个独立的基于TCP的协议。它与HTTP的唯一关系是它的握手被HTTP服务器解释为升级请求。

By default, the WebSocket Protocol uses port 80 for regular WebSocket connections and port 443 for WebSocket connections tunneled over Transport Layer Security (TLS) [RFC2818].

默认情况下,WebSocket协议使用端口80进行常规WebSocket连接,使用端口443通过传输层安全性(TLS)隧道进行WebSocket连接[RFC2818]。

1.8. Establishing a Connection
1.8. 建立联系

_This section is non-normative._

_本节是非规范性的_

When a connection is to be made to a port that is shared by an HTTP server (a situation that is quite likely to occur with traffic to ports 80 and 443), the connection will appear to the HTTP server to be a regular GET request with an Upgrade offer. In relatively simple setups with just one IP address and a single server for all traffic to a single hostname, this might allow a practical way for systems based on the WebSocket Protocol to be deployed. In more elaborate setups (e.g., with load balancers and multiple servers), a dedicated set of hosts for WebSocket connections separate from the HTTP servers is probably easier to manage. At the time of writing of this specification, it should be noted that connections on ports 80 and 443 have significantly different success rates, with connections on port 443 being significantly more likely to succeed, though this may change with time.

当连接到HTTP服务器共享的端口时(这种情况很可能发生在端口80和443的通信量中),HTTP服务器会认为该连接是带有升级服务的常规GET请求。在一个相对简单的设置中,只有一个IP地址和一个服务器,所有流量都可以通过一个主机名,这可能为部署基于WebSocket协议的系统提供了一种实用的方法。在更复杂的设置中(例如,使用负载平衡器和多台服务器),与HTTP服务器分离的WebSocket连接专用主机集可能更容易管理。在编写本规范时,应注意端口80和443上的连接具有显著不同的成功率,端口443上的连接成功的可能性显著增加,尽管这可能会随时间而变化。

1.9. Subprotocols Using the WebSocket Protocol
1.9. 使用WebSocket协议的子目录

_This section is non-normative._

_本节是非规范性的_

The client can request that the server use a specific subprotocol by including the |Sec-WebSocket-Protocol| field in its handshake. If it is specified, the server needs to include the same field and one of the selected subprotocol values in its response for the connection to be established.

客户端可以通过在握手中包含| Sec WebSocket Protocol |字段来请求服务器使用特定的子策略。如果已指定,服务器需要在其响应中包含相同的字段和一个选定的Subtocol值,以便建立连接。

These subprotocol names should be registered as per Section 11.5. To avoid potential collisions, it is recommended to use names that contain the ASCII version of the domain name of the subprotocol's originator. For example, if Example Corporation were to create a Chat subprotocol to be implemented by many servers around the Web, they could name it "chat.example.com". If the Example Organization called their competing subprotocol "chat.example.org", then the two subprotocols could be implemented by servers simultaneously, with the server dynamically selecting which subprotocol to use based on the value sent by the client.

这些子目录名称应按照第11.5节注册。为避免潜在冲突,建议使用包含子策略发起人域名ASCII版本的名称。例如,如果example Corporation要创建一个由Web上的许多服务器实现的聊天子程序,那么他们可以将其命名为“Chat.example.com”。如果示例组织将其竞争的子策略称为“chat.Example.org”,那么这两个子策略可以由服务器同时实现,服务器根据客户端发送的值动态选择要使用的子策略。

Subprotocols can be versioned in backward-incompatible ways by changing the subprotocol name, e.g., going from "bookings.example.net" to "v2.bookings.example.net". These subprotocols would be considered completely separate by WebSocket clients. Backward-compatible versioning can be implemented by reusing the same subprotocol string but carefully designing the actual subprotocol to support this kind of extensibility.

可以通过更改子目录名称(例如,从“bookings.example.net”更改为“v2.bookings.example.net”)以向后不兼容的方式对子目录进行版本控制。WebSocket客户端将认为这些子目录是完全独立的。向后兼容的版本控制可以通过重用相同的子程序字符串来实现,但要仔细设计实际的子程序以支持这种可扩展性。

2. Conformance Requirements
2. 一致性要求

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

本规范中的所有图表、示例和注释都是非规范性的,所有明确标记为非规范性的章节也是如此。本规范中的所有其他内容都是规范性的。

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

本文件中的关键词“必须”、“不得”、“必需”、“应”、“不应”、“应”、“不应”、“建议”、“可”和“可选”应按照[RFC2119]中所述进行解释。

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("MUST", "SHOULD", "MAY", etc.) used in introducing the algorithm.

作为算法一部分的命令式要求(如“去除任何前导空格字符”或“返回false并中止这些步骤”)应使用介绍算法时使用的关键词(“必须”、“应该”、“可能”等)的含义进行解释。

Conformance requirements phrased as algorithms or specific steps MAY be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow and not intended to be performant.)

作为算法或特定步骤的一致性要求可以以任何方式实现,只要最终结果是等效的。(特别是,本规范中定义的算法旨在易于遵循,而非用于执行。)

2.1. Terminology and Other Conventions
2.1. 术语和其他公约

_ASCII_ shall mean the character-encoding scheme defined in [ANSI.X3-4.1986].

_ASCII_uu应指[ANSI.X3-4.1986]中定义的字符编码方案。

This document makes reference to UTF-8 values and uses UTF-8 notational formats as defined in STD 63 [RFC3629].

本文件参考UTF-8值,并使用STD 63[RFC3629]中定义的UTF-8符号格式。

Key terms such as named algorithms or definitions are indicated like _this_.

诸如命名算法或定义之类的关键术语如_this _所示。

Names of header fields or variables are indicated like |this|.

标题字段或变量的名称如| this |所示。

Variable values are indicated like /this/.

变量值如/this/所示。

This document references the procedure to _Fail the WebSocket Connection_. This procedure is defined in Section 7.1.7.

本文档引用了导致WebSocket连接失败的过程。本程序在第7.1.7节中定义。

_Converting a string to ASCII lowercase_ means replacing all characters in the range U+0041 to U+005A (i.e., LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) with the corresponding characters in the range U+0061 to U+007A (i.e., LATIN SMALL LETTER A to LATIN SMALL LETTER Z).

_将字符串转换为ASCII小写字母意味着将U+0041到U+005A范围内的所有字符(即拉丁大写字母a到拉丁大写字母Z)替换为U+0061到U+007A范围内的相应字符(即拉丁小写字母a到拉丁小写字母Z)。

Comparing two strings in an _ASCII case-insensitive_ manner means comparing them exactly, code point for code point, except that the characters in the range U+0041 to U+005A (i.e., LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) and the corresponding characters in the range U+0061 to U+007A (i.e., LATIN SMALL LETTER A to LATIN SMALL LETTER Z) are considered to also match.

以“U ASCII不区分大小写”的方式比较两个字符串意味着以代码点对代码点进行精确比较,但U+0041到U+005A范围内的字符(即拉丁大写字母A到拉丁大写字母Z)和U+0061到U+007A范围内的对应字符(即拉丁小写字母A到拉丁小写字母Z)除外也被认为是匹配的。

The term "URI" is used in this document as defined in [RFC3986].

按照[RFC3986]中的定义,本文件中使用了术语“URI”。

When an implementation is required to _send_ data as part of the WebSocket Protocol, the implementation MAY delay the actual transmission arbitrarily, e.g., buffering data so as to send fewer IP packets.

当需要实现作为WebSocket协议的一部分发送数据时,该实现可以任意延迟实际传输,例如,缓冲数据以便发送更少的IP分组。

Note that this document uses both [RFC5234] and [RFC2616] variants of ABNF in different sections.

请注意,本文档在不同章节中使用了[RFC5234]和[RFC2616]ABNF变体。

3. WebSocket URIs
3. WebSocket URI

This specification defines two URI schemes, using the ABNF syntax defined in RFC 5234 [RFC5234], and terminology and ABNF productions defined by the URI specification RFC 3986 [RFC3986].

本规范使用RFC 5234[RFC5234]中定义的ABNF语法以及URI规范RFC 3986[RFC3986]中定义的术语和ABNF产品定义了两个URI方案。

          ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
          wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
        
          ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
          wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
        
          host = <host, defined in [RFC3986], Section 3.2.2>
          port = <port, defined in [RFC3986], Section 3.2.3>
          path = <path-abempty, defined in [RFC3986], Section 3.3>
          query = <query, defined in [RFC3986], Section 3.4>
        
          host = <host, defined in [RFC3986], Section 3.2.2>
          port = <port, defined in [RFC3986], Section 3.2.3>
          path = <path-abempty, defined in [RFC3986], Section 3.3>
          query = <query, defined in [RFC3986], Section 3.4>
        

The port component is OPTIONAL; the default for "ws" is port 80, while the default for "wss" is port 443.

端口组件是可选的;“ws”的默认值是端口80,“wss”的默认值是端口443。

The URI is called "secure" (and it is said that "the secure flag is set") if the scheme component matches "wss" case-insensitively.

如果方案组件不敏感地匹配“wss”大小写,则URI称为“secure”(据说设置了“secure标志”)。

The "resource-name" (also known as /resource name/ in Section 4.1) can be constructed by concatenating the following:

“资源名称”(在第4.1节中也称为/resource name/)可以通过连接以下内容来构造:

o "/" if the path component is empty

o “/”如果路径组件为空

o the path component

o 路径组件

o "?" if the query component is non-empty

o “?”如果查询组件为非空

o the query component

o 查询组件

Fragment identifiers are meaningless in the context of WebSocket URIs and MUST NOT be used on these URIs. As with any URI scheme, the character "#", when not indicating the start of a fragment, MUST be escaped as %23.

片段标识符在WebSocket URI的上下文中没有意义,不能在这些URI上使用。与任何URI方案一样,当字符“#”不表示片段的开始时,必须将其转义为%23。

4. Opening Handshake
4. 开场握手
4.1. Client Requirements
4.1. 客户要求

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连接,客户端将打开连接并发送本节中定义的握手。连接定义为最初处于连接状态。客户端需要提供/host/、/port/、/resource name/、和/secure/flag,这是第3节中讨论的WebSocket URI的组件,以及要使用的/protocols/和/extensions/列表。此外,如果客户端是web浏览器,则它提供/origin/。

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.

在受控环境中运行的客户端(例如绑定到特定运营商的手机上的浏览器)可能会卸载到网络上另一个代理的连接管理。在这种情况下,出于本规范的目的,客户机被认为包括手持机软件和任何此类代理。

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.

当客户端要建立WebSocket连接时,给定一组(/host/、/port/、/resource name/、和/secure/flag),以及要使用的/protocols/和/extensions/列表,以及一个/origin/(对于web浏览器),它必须打开连接,发送一个打开的握手,并读取服务器的握手响应。关于如何打开连接、在开始握手时应发送什么以及如何解释服务器响应的确切要求,本节如下所示。在下文中,我们将使用第3节中的术语,如该节中定义的“/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.

1. 根据第3节中指定的WebSocket URI规范,传递到此算法中的WebSocket URI组件(/host/、/port/、/resource name/、和/secure/flag)必须有效。如果任何组件无效,客户端必须u使WebSocket连接失败u并中止这些步骤。

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.

2. 如果客户端已经与由/host/和port/port/pair标识的远程主机(IP地址)建立了WebSocket连接,则即使远程主机有其他名称,客户端也必须等待该连接建立或该连接失败。一个连接状态中不能有多个连接。如果同时尝试到同一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地址(例如,因为所有通信都是通过代理服务器完成的,代理服务器本身执行DNS查询),则客户端必须在本步骤中假设每个主机名都指向不同的远程主机,相反,客户端应将同时挂起的连接总数限制在合理的较低数量(例如,客户端可能允许同时挂起到a.example.com和b.example.com的连接,但如果同时请求到单个主机的三十个连接,则可能不允许)。例如,在Web浏览器上下文中,客户端需要考虑用户在设置同时挂起的连接数量的限制时打开的选项卡的数量。

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.

注意:这使得脚本很难通过打开大量到远程主机的WebSocket连接来执行拒绝服务攻击。当受到攻击时,服务器可以通过在关闭连接之前暂停来进一步减少自身的负载,因为这将降低客户端重新连接的速率。

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/.

3. _代理使用:如果客户端配置为在使用WebSocket协议连接到主机/host/和端口/port/时使用代理,则客户端应连接到该代理,并要求它打开到主机/host/和端口/port/的TCP连接。

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:

示例:例如,如果客户端对所有流量使用HTTP代理,则如果要尝试连接到server EXAMPLE.com上的端口80,则可能会向代理服务器发送以下行:

CONNECT example.com:80 HTTP/1.1 Host: example.com

CONNECT example.com:80 HTTP/1.1主机: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=
        
              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/.

如果客户端未配置为使用代理,则应打开与/host/给定的主机和/port/给定的端口的直接TCP连接。

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.

注意:不公开用于为WebSocket连接选择独立于其他代理的代理的显式UI的实现,鼓励使用用于WebSocket连接的SOCKS5[RFC1928]代理(如果可用),或者如果不可用,则建议使用为HTTPS连接配置的代理,而不是为HTTP连接配置的代理。

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.

出于代理自动配置脚本的目的,必须使用第3节中给出的WebSocket URI定义,从/host/、/port/、/resource name/、和/secure/标志构造传递函数的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协议可以在方案中的代理自动配置脚本中识别(“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.

4. 如果由于直接连接失败或使用的任何代理返回错误而无法打开连接,则客户端必须_WebSocket连接失败u并中止连接尝试。

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].

5. 如果/secure/为true,则客户端必须在打开连接后和发送握手数据之前通过连接执行TLS握手[RFC2818]。如果失败(例如,无法验证服务器的证书),则客户端必须_失败WebSocket连接u并中止连接。否则,此通道上的所有进一步通信必须通过加密隧道[RFC5246]进行。

Clients MUST use the Server Name Indication extension in the TLS handshake [RFC6066].

客户端必须在TLS握手[RFC6066]中使用服务器名称指示扩展名。

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升级请求,以及一个必需和可选的头字段列表。此握手的要求如下。

1. The handshake MUST be a valid HTTP request as specified by [RFC2616].

1. 握手必须是[RFC2616]指定的有效HTTP请求。

2. The method of the request MUST be GET, and the HTTP version MUST be at least 1.1.

2. 请求的方法必须是GET,HTTP版本必须至少为1.1。

For example, if the WebSocket URI is "ws://example.com/chat", the first line sent should be "GET /chat 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.

3. 请求的“请求URI”部分必须与第3节(相对URI)中定义的/resource name/匹配,或者是一个绝对http/https URI,在解析时,该URI具有与相应ws/wss URI匹配的/resource name/、/host/、和/port/。

4. The request MUST contain a |Host| header field whose value contains /host/ plus optionally ":" followed by /port/ (when not using the default port).

4. 请求必须包含一个| Host |头字段,其值包含/Host/plus(可选):“后跟/port/(不使用默认端口时)。

5. The request MUST contain an |Upgrade| header field whose value MUST include the "websocket" keyword.

5. 请求必须包含一个| Upgrade |头字段,其值必须包括“websocket”关键字。

6. The request MUST contain a |Connection| header field whose value MUST include the "Upgrade" token.

6. 请求必须包含一个| Connection |头字段,其值必须包括“升级”令牌。

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.

7. 请求必须包含名为| Sec WebSocket Key |的标题字段。此标头字段的值必须是一个nonce,由随机选择的16字节值组成,该值已进行base64编码(参见[RFC4648]第4节)。必须为每个连接随机选择nonce。

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=="

注意:例如,如果随机选择的值是字节序列0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 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.

8. 如果请求来自浏览器客户端,则请求必须包含名为| Origin |[RFC6454]的标题字段。如果连接来自非浏览器客户机,则如果该客户机的语义与此处描述的浏览器客户机用例匹配,则请求可能包括此头字段。此标头字段的值是建立连接的代码正在运行的上下文原点的ASCII序列化。有关如何构造此标头字段值的详细信息,请参见[RFC6454]。

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下载的代码试图建立到ww2.example.com的连接,则header字段的值将为“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.

9. 请求必须包含名为| 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.

注:尽管发布了本文件的草稿版本(-09、-10、-11和-12)(它们主要由编辑更改和澄清组成,而不是对wire协议的更改),但值9、10、11和12未用作Sec WebSocket版本的有效值。这些值在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].

10. 请求可能包括名为| Sec WebSocket Protocol |的标题字段。如果存在,此值表示客户端希望使用的一个或多个逗号分隔的子程序,按首选项排序。组成此值的元素必须是非空字符串,字符范围在U+0021到U+007E之间,不包括[RFC2616]中定义的分隔符,并且必须是唯一字符串。此标头字段值的ABNF为1#标记,其中构造和规则的定义如[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.

11. 请求可能包括名为| 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.

12. 该请求可以包括任何其他报头字段,例如cookie[RFC6265]和/或与认证相关的报头字段,例如|授权|报头字段[RFC2616],这些字段根据定义它们的文档进行处理。

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:

一旦发送了客户端的开始握手,客户端必须等待服务器的响应,然后再发送任何进一步的数据。客户端必须验证服务器的响应,如下所示:

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.

1. 如果从服务器接收到的状态代码不是101,则客户机根据HTTP[RFC2616]过程处理响应。特别地,如果客户端接收到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_.

2. 如果响应缺少| Upgrade |标头字段或| Upgrade |标头字段包含的值与值“websocket”不区分大小写的ASCII匹配,则客户端必须_使websocket连接失败|。

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_.

3. 如果响应缺少| Connection |头字段或| Connection |头字段不包含与值“Upgrade”匹配的ASCII不区分大小写的令牌,则客户端必须_使WebSocket连接失败|。

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_.

4. 如果响应缺少| Sec WebSocket Accept |头字段,或者| Sec WebSocket Accept |包含的值不是| Sec WebSocket Key |与字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”串联的base64编码SHA-1,而是忽略任何前导和尾随空格,客户端必须使WebSocket连接失败。

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.)

5. 如果响应包含| Sec WebSocket Extensions |头字段,并且此头字段表示使用了客户端握手中不存在的扩展(服务器已指示客户端未请求扩展),则客户端必须_使WebSocket连接失败。(第9.1节讨论了解析此标头字段以确定请求哪些扩展。)

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_.

6. 如果响应包含| Sec WebSocket Protocol |头字段,并且此头字段表示使用了客户端握手中不存在的子策略(服务器已指示客户端未请求的子策略),则客户端必须_使WebSocket连接失败|。

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节中定义的服务器握手要求,则客户端必须使WebSocket连接失败。

Please note that according to [RFC2616], all header field names in both HTTP requests and HTTP responses are case-insensitive.

请注意,根据[RFC2616],HTTP请求和HTTP响应中的所有头字段名称都不区分大小写。

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_.

如果服务器的响应按照上述规定进行验证,则表示WebSocket连接已建立WebSocket连接处于打开状态。_Extensions In Use_uu被定义为一个(可能为空)字符串,其值等于服务器握手提供的| Sec WebSocket Extensions |头字段的值,或者如果该头字段在服务器握手中不存在,则等于空值。_subtocol In Use_被定义为服务器握手中的| Sec WebSocket Protocol |头字段的值,或者如果该头字段在服务器握手中不存在,则为空值。此外,如果服务器握手中的任何头字段指示应设置Cookie(如[RFC6265]所定义),则这些Cookie称为在服务器开始握手期间设置的_Cookie。

4.2. Server-Side Requirements
4.2. 服务器端要求

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.

服务器可以卸载与网络上其他代理(例如,负载平衡器和反向代理)的连接管理。在这种情况下,出于本规范的目的,服务器被视为包括从第一个设备到处理请求和发送响应的服务器终止TCP连接的服务器端基础设施的所有部分。

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请求,然后将连接传递到另一台服务器以实际处理数据帧。在本规范中,“服务器”是两台计算机的组合。

4.2.1. Reading the Client's Opening Handshake
4.2.1. 阅读客户的开场握手

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连接时,它会发送开始握手的一部分。服务器必须至少解析此握手的一部分,以便获得生成握手的服务器部分所需的信息。

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).

客户的开场握手包括以下几个部分。如果服务器在读取握手时发现客户端未发送与以下描述匹配的握手(请注意,根据[RFC2616],头字段的顺序并不重要),包括但不限于任何违反为握手组件指定的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. HTTP/1.1或更高版本的GET请求,包括“请求URI”[RFC2616],应解释为第3节中定义的/resource name/(或包含/resource name/)的绝对HTTP/HTTPS URI)。

2. A |Host| header field containing the server's authority.

2. 包含服务器权限的|主机|头字段。

3. An |Upgrade| header field containing the value "websocket", treated as an ASCII case-insensitive value.

3. 包含值“websocket”的| Upgrade |标头字段,被视为ASCII不区分大小写的值。

4. A |Connection| header field that includes the token "Upgrade", treated as an ASCII case-insensitive value.

4. 一个| Connection |头字段,包括标记“Upgrade”,被视为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.

5. 一个| Sec WebSocket Key |头字段,带有base64编码(参见[RFC4648]第4节)值,解码时长度为16字节。

6. A |Sec-WebSocket-Version| header field, with a value of 13.

6. 一个| Sec WebSocket版本|标题字段,值为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.

7. (可选)一个|原点|标题字段。此标题字段由所有浏览器客户端发送。不应将缺少此标头字段的连接尝试解释为来自浏览器客户端。

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.

8. (可选)一个| 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.

9. (可选)一个| 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].

10. (可选)其他标头字段,例如用于向服务器发送cookie或请求身份验证的字段。根据[RFC2616],忽略未知标头字段。

4.2.2. Sending the Server's Opening Handshake
4.2.2. 发送服务器的开始握手

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].

1. 如果连接发生在HTTPS(HTTP over TLS)端口上,请通过连接执行TLS握手。如果失败(例如,客户机在扩展客户机hello“server_name”扩展中指示了一个主机名,而服务器没有主机),则关闭连接;否则,连接的所有进一步通信(包括服务器的握手)必须通过加密隧道[RFC5246]运行。

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].

2. 服务器可以执行额外的客户端身份验证,例如,通过返回401状态码和相应的| WWW Authenticate |头字段,如[RFC2616]中所述。

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.

3. 服务器可以使用3xx状态代码[RFC2616]重定向客户端。请注意,此步骤可以与上述可选身份验证步骤同时进行,也可以在该步骤之前或之后进行。

4. Establish the following information:

4. 确定以下信息:

/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/客户端握手中的| origin |头字段指示建立连接的脚本的来源。原点序列化为ASCII并转换为小写。服务器可以使用此信息作为确定是否接受传入连接的一部分。如果服务器不验证源站,它将接受来自任何地方的连接。如果服务器不希望接受此连接,则必须返回适当的HTTP错误代码(例如403禁止),并中止本节中描述的WebSocket握手。有关更多详细信息,请参阅第10节。

/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.

/key/客户端握手中的| Sec WebSocket key |头字段包括一个base64编码值,如果解码,长度为16字节。此(编码)值用于创建服务器握手,以表示接受连接。服务器无需对| Sec WebSocket Key |值进行base64解码。

/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升级)和| Sec WebSocket version |头字段,指示服务器能够理解的版本。

/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.

/资源名称/服务器提供的服务的标识符。如果服务器提供多个服务,那么该值应该从GET方法的“Request URI”[RFC2616]中客户端握手中给出的资源名称中派生。如果请求的服务不可用,服务器必须发送适当的HTTP错误代码(例如404 not Found)并中止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].

/Subtocol/表示服务器准备使用的Subtocol的单个值或null。选择的值必须来自客户端的握手,特别是从服务器愿意用于此连接的| Sec WebSocket Protocol |字段中选择一个值(如果有)。如果客户端的握手不包含这样的头字段,或者如果服务器不同意客户端请求的任何子脚本,则唯一可接受的值为null。缺少此类字段相当于空值(这意味着,如果服务器不希望同意其中一个建议的子策略,则它不得在其响应中发回| Sec WebSocket Protocol | header字段)。出于这些目的,空字符串与空值不同,并且不是此字段的合法值。此头字段值的ABNF为(令牌),其中构造和规则的定义如[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

/extensions/A(可能为空)列表,表示服务器准备使用的协议级扩展。如果服务器支持多个扩展,则该值必须从客户端的握手中派生出来,特别是从| Sec WebSocket extensions |字段中选择一个或多个值。缺少这样的字段相当于空值。空字符串与这些字符串的null值不同

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.

目的。不能列出客户端未列出的扩展。第9.1节讨论了选择和解释这些值的方法。

5. If the server chooses to accept the incoming connection, it MUST reply with a valid HTTP response indicating the following.

5. 如果服务器选择接受传入连接,它必须使用有效的HTTP响应进行响应,该响应指示以下内容。

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".

1. 根据RFC 2616[RFC2616]的要求,状态行带有101响应代码。这样的响应可能类似于“HTTP/1.1 101交换协议”。

2. An |Upgrade| header field with value "websocket" as per RFC 2616 [RFC2616].

2. 根据RFC 2616[RFC2616]的规定,带有值“websocket”的| Upgrade |标头字段。

3. A |Connection| header field with value "Upgrade".

3. 值为“升级”的|连接|标题字段。

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.

4. 一个|秒WebSocket接受|标题字段。此标头字段的值是通过将上文第4.2.2节步骤4中定义的/key/与字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”串联而成的,该串接值的SHA-1散列用于获得20字节值和该20字节散列的base64编码(参见[RFC4648]第4节)。

The ABNF [RFC2616] of this header field is defined as follows:

此标头字段的ABNF[RFC2616]定义如下:

           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 | "+" | "/"
        
           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 | header字段的值为“dghlhhbxbszub25jzq==”,服务器将附加字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”以形成字符串“dghlhhbxbszub25jzq==258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。然后,服务器将获取该字符串的SHA-1散列,给出值0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 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.

5. (可选)一个| Sec WebSocket Protocol |头字段,其值/subtocol/如第4.2.2节步骤4所定义。

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.

6. (可选)一个| Sec WebSocket Extensions |标题字段,其值/扩展名/如第4.2.2节步骤4所定义。如果要使用多个扩展,则可以将它们全部列在单个| 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连接已建立,并且WebSocket连接处于打开状态。此时,服务器可能开始发送(和接收)数据。

4.3. Collected ABNF for New Header Fields Used in Handshake
4.3. 为握手中使用的新标头字段收集ABNF

This section is using ABNF syntax/rules from Section 2.1 of [RFC2616], including the "implied *LWS rule".

本节使用[RFC2616]第2.1节中的ABNF语法/规则,包括“隐含*LWS规则”。

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 |标题字段值的语法。名称中带有“-Client”后缀的ABNF规则仅用于客户端向服务器发送的请求;名称中带有“-Server”后缀的ABNF规则仅用于服务器发送给客户端的响应。例如,ABNF规则Sec WebSocket协议客户端描述了客户端发送到服务器的| Sec WebSocket协议|头字段值的语法。

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

Sec WebSocket Key=base64值非空Sec WebSocket Extensions=扩展列表Sec WebSocket协议客户端=1#令牌Sec WebSocket版本客户端=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
        
      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
        
      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

Sec WebSocket Extensions=扩展列表Sec WebSocket Accept=base64值非空Sec WebSocket协议服务器=令牌Sec WebSocket版本服务器=1#版本

4.4. Supporting Multiple Versions of WebSocket Protocol
4.4. 支持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.
        
   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.
        

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

GET/chat HTTP/1.1主机:server.example.com升级:websocket连接:升级。。。Sec WebSocket版本:25

The response from the server might look as follows:

来自服务器的响应可能如下所示:

HTTP/1.1 400 Bad Request ... Sec-WebSocket-Version: 13, 8, 7

HTTP/1.1 400错误请求。。。Sec WebSocket版本: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

HTTP/1.1 400错误请求。。。秒WebSocket版本:13秒WebSocket版本:8,7

The client now repeats the handshake that conforms to version 13:

客户端现在重复符合版本13的握手:

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

GET/chat HTTP/1.1主机:server.example.com升级:websocket连接:升级。。。Sec WebSocket版本:13

5. Data Framing
5. 数据帧
5.1. Overview
5.1. 概述

In the WebSocket Protocol, data is transmitted using a sequence of frames. To avoid confusing network intermediaries (such as intercepting proxies) and for security reasons that are further discussed in Section 10.3, a client MUST mask all frames that it sends to the server (see Section 5.3 for further details). (Note that masking is done whether or not the WebSocket Protocol is running over TLS.) The server MUST close the connection upon receiving a frame that is not masked. In this case, a server MAY send a Close frame with a status code of 1002 (protocol error) as defined in Section 7.4.1. A server MUST NOT mask any frames that it sends to the client. A client MUST close a connection if it detects a masked frame. In this case, it MAY use the status code 1002 (protocol error) as defined in Section 7.4.1. (These rules might be relaxed in a future specification.)

在WebSocket协议中,使用帧序列传输数据。为了避免混淆网络中介(如拦截代理)以及出于第10.3节中进一步讨论的安全原因,客户端必须屏蔽其发送到服务器的所有帧(有关更多详细信息,请参阅第5.3节)。(请注意,无论WebSocket协议是否在TLS上运行,都会进行屏蔽。)服务器必须在收到未屏蔽的帧时关闭连接。在这种情况下,服务器可发送状态代码为1002(协议错误)的闭合帧,如第7.4.1节所定义。服务器不得屏蔽发送给客户端的任何帧。如果客户端检测到屏蔽帧,则必须关闭连接。在这种情况下,可使用第7.4.1节中定义的状态代码1002(协议错误)。(这些规则在未来的规范中可能会放宽。)

The base framing protocol defines a frame type with an opcode, a payload length, and designated locations for "Extension data" and "Application data", which together define the "Payload data". Certain bits and opcodes are reserved for future expansion of the protocol.

基本帧协议使用操作码、有效负载长度以及“扩展数据”和“应用数据”的指定位置来定义帧类型,这两者一起定义了“有效负载数据”。某些位和操作码保留用于协议的未来扩展。

A data frame MAY be transmitted by either the client or the server at any time after opening handshake completion and before that endpoint has sent a Close frame (Section 5.5.1).

在开放握手完成后和端点发送闭合帧之前,客户机或服务器可随时发送数据帧(第5.5.1节)。

5.2. Base Framing Protocol
5.2. 基本帧协议

This wire format for the data transfer part is described by the ABNF [RFC5234] given in detail in this section. (Note that, unlike in other sections of this document, the ABNF in this section is operating on groups of bits. The length of each group of bits is indicated in a comment. When encoded on the wire, the most significant bit is the leftmost in the ABNF). A high-level overview of the framing is given in the following figure. In a case of conflict between the figure below and the ABNF specified later in this section, the figure is authoritative.

本节详细介绍了ABNF[RFC5234]中描述的数据传输部分的导线格式。(请注意,与本文件其他章节不同,本节中的ABNF是在一组位上操作的。每组位的长度在注释中表示。在导线上编码时,最高有效位是ABNF中最左边的位)。下图给出了框架的高级概述。如果下图与本节后面指定的ABNF之间存在冲突,则该图具有权威性。

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+
        
      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+
        

FIN: 1 bit

鳍:1位

Indicates that this is the final fragment in a message. The first fragment MAY also be the final fragment.

指示这是消息中的最后一个片段。第一个片段也可能是最后一个片段。

RSV1, RSV2, RSV3: 1 bit each

RSV1、RSV2、RSV3:各1位

MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. If a nonzero value is received and none of the negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST _Fail the WebSocket Connection_.

必须为0,除非协商定义非零值含义的扩展。如果接收到一个非零值,并且协商扩展中没有一个定义了这样一个非零值的含义,那么接收端点必须使WebSocket连接失败。

Opcode: 4 bits

操作码:4位

Defines the interpretation of the "Payload data". If an unknown opcode is received, the receiving endpoint MUST _Fail the WebSocket Connection_. The following values are defined.

定义“有效载荷数据”的解释。如果接收到未知操作码,则接收端点必须使WebSocket连接失败。定义了以下值。

* %x0 denotes a continuation frame

* %x0表示连续帧

* %x1 denotes a text frame

* %x1表示文本框

* %x2 denotes a binary frame

* %x2表示二进制帧

* %x3-7 are reserved for further non-control frames

* %x3-7预留用于其他非控制帧

* %x8 denotes a connection close

* %x8表示连接关闭

* %x9 denotes a ping

* %x9表示ping

* %xA denotes a pong

* %xA表示乒乓球

* %xB-F are reserved for further control frames

* %xB-F保留用于进一步的控制帧

Mask: 1 bit

掩码:1位

Defines whether the "Payload data" is masked. If set to 1, a masking key is present in masking-key, and this is used to unmask the "Payload data" as per Section 5.3. All frames sent from client to server have this bit set to 1.

定义是否屏蔽“有效负载数据”。如果设置为1,则屏蔽密钥中存在一个屏蔽密钥,该密钥用于根据第5.3节解除“有效负载数据”的屏蔽。从客户端发送到服务器的所有帧都将此位设置为1。

   Payload length:  7 bits, 7+16 bits, or 7+64 bits
        
   Payload length:  7 bits, 7+16 bits, or 7+64 bits
        

The length of the "Payload data", in bytes: if 0-125, that is the payload length. If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length. Multibyte length quantities are expressed in network byte order. Note that in all cases, the minimal number of bytes MUST be used to encode the length, for example, the length of a 124-byte-long string can't be encoded as the sequence 126, 0, 124. The payload length is the length of the "Extension data" + the length of the "Application data". The length of the "Extension data" may be zero, in which case the payload length is the length of the "Application data".

“有效负载数据”的长度,以字节为单位:如果为0-125,则为有效负载长度。如果为126,则以下解释为16位无符号整数的2个字节为有效负载长度。如果为127,则以下解释为64位无符号整数(最高有效位必须为0)的8个字节为有效负载长度。多字节长度量以网络字节顺序表示。请注意,在所有情况下,必须使用最小字节数来编码长度,例如,124字节长字符串的长度不能被编码为序列126、0、124。有效负载长度是“扩展数据”的长度+“应用数据”的长度。“扩展数据”的长度可以是零,在这种情况下,有效载荷长度是“应用数据”的长度。

Masking-key: 0 or 4 bytes

屏蔽密钥:0或4字节

All frames sent from the client to the server are masked by a 32-bit value that is contained within the frame. This field is present if the mask bit is set to 1 and is absent if the mask bit is set to 0. See Section 5.3 for further information on client-to-server masking.

从客户端发送到服务器的所有帧都被包含在帧中的32位值屏蔽。如果掩码位设置为1,则此字段存在;如果掩码位设置为0,则此字段不存在。有关客户端到服务器屏蔽的更多信息,请参见第5.3节。

Payload data: (x+y) bytes

有效负载数据:(x+y)字节

The "Payload data" is defined as "Extension data" concatenated with "Application data".

“有效负载数据”被定义为与“应用程序数据”连接的“扩展数据”。

Extension data: x bytes

扩展数据:x字节

The "Extension data" is 0 bytes unless an extension has been negotiated. Any extension MUST specify the length of the "Extension data", or how that length may be calculated, and how the extension use MUST be negotiated during the opening handshake. If present, the "Extension data" is included in the total payload length.

除非已协商扩展,“扩展数据”为0字节。任何分机都必须指定“分机数据”的长度,或者如何计算该长度,以及在开始握手期间必须如何协商分机的使用。如果存在,“扩展数据”包括在总有效负载长度中。

Application data: y bytes

应用程序数据:y字节

Arbitrary "Application data", taking up the remainder of the frame after any "Extension data". The length of the "Application data" is equal to the payload length minus the length of the "Extension data".

任意“应用程序数据”,占用任何“扩展数据”之后的剩余帧。“应用数据”的长度等于有效负载长度减去“扩展数据”的长度。

The base framing protocol is formally defined by the following ABNF [RFC5234]. It is important to note that the representation of this data is binary, not ASCII characters. As such, a field with a length of 1 bit that takes values %x0 / %x1 is represented as a single bit whose value is 0 or 1, not a full byte (octet) that stands for the characters "0" or "1" in the ASCII encoding. A field with a length of 4 bits with values between %x0-F again is represented by 4 bits, again NOT by an ASCII character or full byte (octet) with these values. [RFC5234] does not specify a character encoding: "Rules resolve into a string of terminal values, sometimes called characters. In ABNF, a character is merely a non-negative integer. In certain contexts, a specific mapping (encoding) of values into a character set (such as ASCII) will be specified." Here, the specified encoding is a binary encoding where each terminal value is encoded in the specified number of bits, which varies for each field.

基本帧协议由以下ABNF[RFC5234]正式定义。需要注意的是,此数据的表示形式是二进制字符,而不是ASCII字符。因此,采用值%x0/%x1的长度为1位的字段表示为值为0或1的单个位,而不是表示ASCII编码中字符“0”或“1”的完整字节(八位字节)。长度为4位且值介于%x0-F之间的字段同样由4位表示,而不是由具有这些值的ASCII字符或完整字节(八位字节)表示。[RFC5234]未指定字符编码:“规则解析为一组终端值,有时称为字符。在ABNF中,字符仅为非负整数。在某些上下文中,将指定值到字符集(如ASCII)的特定映射(编码)。”,指定的编码是二进制编码,其中每个终端值以指定的位数编码,每个字段的位数不同。

    ws-frame                = frame-fin           ; 1 bit in length
                              frame-rsv1          ; 1 bit in length
                              frame-rsv2          ; 1 bit in length
                              frame-rsv3          ; 1 bit in length
                              frame-opcode        ; 4 bits in length
                              frame-masked        ; 1 bit in length
                              frame-payload-length   ; either 7, 7+16,
                                                     ; or 7+64 bits in
                                                     ; length
                              [ frame-masking-key ]  ; 32 bits in length
                              frame-payload-data     ; n*8 bits in
                                                     ; length, where
                                                     ; n >= 0
        
    ws-frame                = frame-fin           ; 1 bit in length
                              frame-rsv1          ; 1 bit in length
                              frame-rsv2          ; 1 bit in length
                              frame-rsv3          ; 1 bit in length
                              frame-opcode        ; 4 bits in length
                              frame-masked        ; 1 bit in length
                              frame-payload-length   ; either 7, 7+16,
                                                     ; or 7+64 bits in
                                                     ; length
                              [ frame-masking-key ]  ; 32 bits in length
                              frame-payload-data     ; n*8 bits in
                                                     ; length, where
                                                     ; n >= 0
        
    frame-fin               = %x0 ; more frames of this message follow
                            / %x1 ; final frame of this message
                                  ; 1 bit in length
        
    frame-fin               = %x0 ; more frames of this message follow
                            / %x1 ; final frame of this message
                                  ; 1 bit in length
        
    frame-rsv1              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
        
    frame-rsv1              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
        
    frame-rsv2              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
        
    frame-rsv2              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
        
    frame-rsv3              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
        
    frame-rsv3              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
        

frame-opcode = frame-opcode-non-control / frame-opcode-control / frame-opcode-cont

帧操作码=帧操作码非控制/帧操作码控制/帧操作码控制

    frame-opcode-cont       = %x0 ; frame continuation
        
    frame-opcode-cont       = %x0 ; frame continuation
        
    frame-opcode-non-control= %x1 ; text frame
                            / %x2 ; binary frame
                            / %x3-7
                            ; 4 bits in length,
                            ; reserved for further non-control frames
        
    frame-opcode-non-control= %x1 ; text frame
                            / %x2 ; binary frame
                            / %x3-7
                            ; 4 bits in length,
                            ; reserved for further non-control frames
        
    frame-opcode-control    = %x8 ; connection close
                            / %x9 ; ping
                            / %xA ; pong
                            / %xB-F ; reserved for further control
                                    ; frames
                                    ; 4 bits in length
        
    frame-opcode-control    = %x8 ; connection close
                            / %x9 ; ping
                            / %xA ; pong
                            / %xB-F ; reserved for further control
                                    ; frames
                                    ; 4 bits in length
        
    frame-masked            = %x0
                            ; frame is not masked, no frame-masking-key
                            / %x1
                            ; frame is masked, frame-masking-key present
                            ; 1 bit in length
        
    frame-masked            = %x0
                            ; frame is not masked, no frame-masking-key
                            / %x1
                            ; frame is masked, frame-masking-key present
                            ; 1 bit in length
        
    frame-payload-length    = ( %x00-7D )
                            / ( %x7E frame-payload-length-16 )
                            / ( %x7F frame-payload-length-63 )
                            ; 7, 7+16, or 7+64 bits in length,
                            ; respectively
        
    frame-payload-length    = ( %x00-7D )
                            / ( %x7E frame-payload-length-16 )
                            / ( %x7F frame-payload-length-63 )
                            ; 7, 7+16, or 7+64 bits in length,
                            ; respectively
        
    frame-payload-length-16 = %x0000-FFFF ; 16 bits in length
        
    frame-payload-length-16 = %x0000-FFFF ; 16 bits in length
        
    frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
                            ; 64 bits in length
        
    frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
                            ; 64 bits in length
        

frame-masking-key = 4( %x00-FF ) ; present only if frame-masked is 1 ; 32 bits in length

帧屏蔽键=4(%x00 FF);仅当遮罩的帧为1时出现;长度为32位

    frame-payload-data      = (frame-masked-extension-data
                               frame-masked-application-data)
                            ; when frame-masked is 1
                              / (frame-unmasked-extension-data
                                frame-unmasked-application-data)
                            ; when frame-masked is 0
        
    frame-payload-data      = (frame-masked-extension-data
                               frame-masked-application-data)
                            ; when frame-masked is 1
                              / (frame-unmasked-extension-data
                                frame-unmasked-application-data)
                            ; when frame-masked is 0
        
    frame-masked-extension-data     = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0
        
    frame-masked-extension-data     = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0
        
    frame-masked-application-data   = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0
        
    frame-masked-application-data   = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0
        
    frame-unmasked-extension-data   = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0
        
    frame-unmasked-extension-data   = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0
        
    frame-unmasked-application-data = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0
        
    frame-unmasked-application-data = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0
        
5.3. Client-to-Server Masking
5.3. 客户端到服务器屏蔽

A masked frame MUST have the field frame-masked set to 1, as defined in Section 5.2.

如第5.2节所定义,屏蔽帧必须将字段帧屏蔽设置为1。

The masking key is contained completely within the frame, as defined in Section 5.2 as frame-masking-key. It is used to mask the "Payload data" defined in the same section as frame-payload-data, which includes "Extension data" and "Application data".

屏蔽键完全包含在框架内,如第5.2节定义为框架屏蔽键。它用于屏蔽在与帧有效载荷数据相同的部分中定义的“有效载荷数据”,包括“扩展数据”和“应用数据”。

The masking key is a 32-bit value chosen at random by the client. When preparing a masked frame, the client MUST pick a fresh masking key from the set of allowed 32-bit values. The masking key needs to be unpredictable; thus, the masking key MUST be derived from a strong source of entropy, and the masking key for a given frame MUST NOT make it simple for a server/proxy to predict the masking key for a subsequent frame. The unpredictability of the masking key is essential to prevent authors of malicious applications from selecting the bytes that appear on the wire. RFC 4086 [RFC4086] discusses what entails a suitable source of entropy for security-sensitive applications.

屏蔽密钥是由客户端随机选择的32位值。准备屏蔽帧时,客户端必须从允许的32位值集中选择一个新的屏蔽密钥。屏蔽键需要是不可预测的;因此,屏蔽密钥必须来自强熵源,并且给定帧的屏蔽密钥不能使服务器/代理预测后续帧的屏蔽密钥变得简单。屏蔽密钥的不可预测性对于防止恶意应用程序的作者选择出现在线路上的字节至关重要。RFC 4086[RFC4086]讨论了什么需要为安全敏感应用程序提供合适的熵源。

The masking does not affect the length of the "Payload data". To convert masked data into unmasked data, or vice versa, the following algorithm is applied. The same algorithm applies regardless of the direction of the translation, e.g., the same steps are applied to mask the data as to unmask the data.

屏蔽不会影响“有效负载数据”的长度。要将屏蔽数据转换为未屏蔽数据,或将其转换为未屏蔽数据,请应用以下算法。无论平移的方向如何,都应用相同的算法,例如,用于屏蔽数据的步骤与用于解除屏蔽数据的步骤相同。

Octet i of the transformed data ("transformed-octet-i") is the XOR of octet i of the original data ("original-octet-i") with octet at index i modulo 4 of the masking key ("masking-key-octet-j"):

转换数据的八位位组i(“转换的八位位组i”)是原始数据的八位位组i(“原始八位位组i”)与掩蔽键的索引i模4处的八位位组(“掩蔽键八位位组j”)的异或:

j = i MOD 4 transformed-octet-i = original-octet-i XOR masking-key-octet-j

j=i MOD 4 transformed-octet-i=original-octet-i异或掩蔽-key-octet-j

The payload length, indicated in the framing as frame-payload-length, does NOT include the length of the masking key. It is the length of the "Payload data", e.g., the number of bytes following the masking key.

帧中指示为帧有效负载长度的有效负载长度不包括屏蔽键的长度。它是“有效负载数据”的长度,例如,屏蔽键后的字节数。

5.4. Fragmentation
5.4. 碎裂

The primary purpose of fragmentation is to allow sending a message that is of unknown size when the message is started without having to buffer that message. If messages couldn't be fragmented, then an endpoint would have to buffer the entire message so its length could be counted before the first byte is sent. With fragmentation, a server or intermediary may choose a reasonable size buffer and, when the buffer is full, write a fragment to the network.

分段的主要目的是允许在消息启动时发送大小未知的消息,而不必缓冲该消息。如果消息不能分段,那么端点必须缓冲整个消息,以便在发送第一个字节之前计算其长度。对于碎片,服务器或中介可以选择合理大小的缓冲区,当缓冲区已满时,将碎片写入网络。

A secondary use-case for fragmentation is for multiplexing, where it is not desirable for a large message on one logical channel to monopolize the output channel, so the multiplexing needs to be free

分段的第二个用例用于多路复用,其中不希望一个逻辑通道上的大消息独占输出通道,因此多路复用需要是免费的

to split the message into smaller fragments to better share the output channel. (Note that the multiplexing extension is not described in this document.)

将消息拆分为更小的片段,以便更好地共享输出通道。(请注意,本文档中未描述多路复用扩展。)

Unless specified otherwise by an extension, frames have no semantic meaning. An intermediary might coalesce and/or split frames, if no extensions were negotiated by the client and the server or if some extensions were negotiated, but the intermediary understood all the extensions negotiated and knows how to coalesce and/or split frames in the presence of these extensions. One implication of this is that in absence of extensions, senders and receivers must not depend on the presence of specific frame boundaries.

除非扩展另有规定,否则框架没有语义意义。如果客户机和服务器没有协商扩展,或者协商了一些扩展,则中介可以合并和/或拆分帧,但是中介了解协商的所有扩展,并且知道如何在这些扩展存在的情况下合并和/或拆分帧。这意味着在没有扩展的情况下,发送方和接收方不能依赖于特定帧边界的存在。

The following rules apply to fragmentation:

以下规则适用于碎片:

o An unfragmented message consists of a single frame with the FIN bit set (Section 5.2) and an opcode other than 0.

o 未分段消息由设置了FIN位的单个帧(第5.2节)和非0的操作码组成。

o A fragmented message consists of a single frame with the FIN bit clear and an opcode other than 0, followed by zero or more frames with the FIN bit clear and the opcode set to 0, and terminated by a single frame with the FIN bit set and an opcode of 0. A fragmented message is conceptually equivalent to a single larger message whose payload is equal to the concatenation of the payloads of the fragments in order; however, in the presence of extensions, this may not hold true as the extension defines the interpretation of the "Extension data" present. For instance, "Extension data" may only be present at the beginning of the first fragment and apply to subsequent fragments, or there may be "Extension data" present in each of the fragments that applies only to that particular fragment. In the absence of "Extension data", the following example demonstrates how fragmentation works.

o 分段消息由一个FIN位为clear的单帧和一个非0的操作码组成,然后是零个或多个FIN位为clear且操作码设置为0的帧,并由一个FIN位为set且操作码为0的单帧终止。碎片化消息在概念上等同于单个较大消息,其有效载荷等于按顺序连接的碎片有效载荷;然而,在存在扩展的情况下,这可能不成立,因为扩展定义了现有“扩展数据”的解释。例如,“扩展数据”可能仅出现在第一个片段的开头并应用于后续片段,或者在每个片段中可能存在仅适用于该特定片段的“扩展数据”。在缺少“扩展数据”的情况下,下面的示例演示了碎片是如何工作的。

EXAMPLE: For a text message sent as three fragments, the first fragment would have an opcode of 0x1 and a FIN bit clear, the second fragment would have an opcode of 0x0 and a FIN bit clear, and the third fragment would have an opcode of 0x0 and a FIN bit that is set.

示例:对于作为三个片段发送的文本消息,第一个片段的操作码为0x1,FIN位清除,第二个片段的操作码为0x0,FIN位清除,第三个片段的操作码为0x0,FIN位已设置。

o Control frames (see Section 5.5) MAY be injected in the middle of a fragmented message. Control frames themselves MUST NOT be fragmented.

o 控制帧(参见第5.5节)可以在分段消息的中间注入。控制框架本身不得被分割。

o Message fragments MUST be delivered to the recipient in the order sent by the sender.

o 邮件片段必须按照发件人发送的顺序发送给收件人。

o The fragments of one message MUST NOT be interleaved between the fragments of another message unless an extension has been negotiated that can interpret the interleaving.

o 一条消息的片段不能在另一条消息的片段之间交错,除非已经协商了可以解释交错的扩展。

o An endpoint MUST be capable of handling control frames in the middle of a fragmented message.

o 端点必须能够在碎片化消息的中间处理控制帧。

o A sender MAY create fragments of any size for non-control messages.

o 发送方可以为非控制消息创建任意大小的片段。

o Clients and servers MUST support receiving both fragmented and unfragmented messages.

o 客户端和服务器必须支持接收分段和未分段的消息。

o As control frames cannot be fragmented, an intermediary MUST NOT attempt to change the fragmentation of a control frame.

o 由于控制帧不能分段,中间层不得尝试更改控制帧的分段。

o An intermediary MUST NOT change the fragmentation of a message if any reserved bit values are used and the meaning of these values is not known to the intermediary.

o 如果使用了任何保留位值,并且中间层不知道这些值的含义,则中间层不得更改消息的分段。

o An intermediary MUST NOT change the fragmentation of any message in the context of a connection where extensions have been negotiated and the intermediary is not aware of the semantics of the negotiated extensions. Similarly, an intermediary that didn't see the WebSocket handshake (and wasn't notified about its content) that resulted in a WebSocket connection MUST NOT change the fragmentation of any message of such connection.

o 在已协商扩展且中介不知道协商扩展的语义的连接上下文中,中介不得更改任何消息的分段。类似地,未看到导致WebSocket连接的WebSocket握手(且未通知其内容)的中介不得更改此类连接的任何消息的碎片。

o As a consequence of these rules, all fragments of a message are of the same type, as set by the first fragment's opcode. Since control frames cannot be fragmented, the type for all fragments in a message MUST be either text, binary, or one of the reserved opcodes.

o 作为这些规则的结果,消息的所有片段都是由第一个片段的操作码设置的相同类型。由于控制帧不能分段,因此消息中所有分段的类型必须是文本、二进制或保留操作码之一。

NOTE: If control frames could not be interjected, the latency of a ping, for example, would be very long if behind a large message. Hence, the requirement of handling control frames in the middle of a fragmented message.

注意:如果无法中断控制帧,例如,如果在大消息后面,ping的延迟将非常长。因此,需要在碎片化消息的中间处理控制帧。

IMPLEMENTATION NOTE: In the absence of any extension, a receiver doesn't have to buffer the whole frame in order to process it. For example, if a streaming API is used, a part of a frame can be delivered to the application. However, note that this assumption might not hold true for all future WebSocket extensions.

实现注意:在没有任何扩展的情况下,接收器不必为了处理它而缓冲整个帧。例如,如果使用流式API,则可以将帧的一部分传递给应用程序。但是,请注意,这个假设可能并不适用于将来所有的WebSocket扩展。

5.5. Control Frames
5.5. 控制帧

Control frames are identified by opcodes where the most significant bit of the opcode is 1. Currently defined opcodes for control frames include 0x8 (Close), 0x9 (Ping), and 0xA (Pong). Opcodes 0xB-0xF are reserved for further control frames yet to be defined.

控制帧由操作码标识,其中操作码的最高有效位为1。当前为控制帧定义的操作码包括0x8(关闭)、0x9(Ping)和0xA(Pong)。操作码0xB-0xF保留用于尚待定义的其他控制帧。

Control frames are used to communicate state about the WebSocket. Control frames can be interjected in the middle of a fragmented message.

控制帧用于传递有关WebSocket的状态。控制帧可以在碎片化消息的中间插入。

All control frames MUST have a payload length of 125 bytes or less and MUST NOT be fragmented.

所有控制帧的有效负载长度必须小于等于125字节,并且不得分段。

5.5.1. Close
5.5.1. 关

The Close frame contains an opcode of 0x8.

闭合帧包含0x8的操作码。

The Close frame MAY contain a body (the "Application data" portion of the frame) that indicates a reason for closing, such as an endpoint shutting down, an endpoint having received a frame too large, or an endpoint having received a frame that does not conform to the format expected by the endpoint. If there is a body, the first two bytes of the body MUST be a 2-byte unsigned integer (in network byte order) representing a status code with value /code/ defined in Section 7.4. Following the 2-byte integer, the body MAY contain UTF-8-encoded data with value /reason/, the interpretation of which is not defined by this specification. This data is not necessarily human readable but may be useful for debugging or passing information relevant to the script that opened the connection. As the data is not guaranteed to be human readable, clients MUST NOT show it to end users.

关闭帧可以包含指示关闭原因的主体(帧的“应用程序数据”部分),例如端点关闭、端点接收到过大的帧或端点接收到不符合端点预期格式的帧。如果有正文,正文的前两个字节必须是2字节无符号整数(按网络字节顺序),表示第7.4节中定义的值为/code/的状态代码。在2字节整数之后,正文可能包含值为/reason/的UTF-8编码数据,其解释不在本规范中定义。这些数据不一定是人类可读的,但可能有助于调试或传递与打开连接的脚本相关的信息。由于不能保证数据是人类可读的,因此客户端不能向最终用户显示数据。

Close frames sent from client to server must be masked as per Section 5.3.

根据第5.3节,必须屏蔽从客户端发送到服务器的关闭帧。

The application MUST NOT send any more data frames after sending a Close frame.

在发送闭合帧后,应用程序不得再发送任何数据帧。

If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint MUST send a Close frame in response. (When sending a Close frame in response, the endpoint typically echos the status code it received.) It SHOULD do so as soon as practical. An endpoint MAY delay sending a Close frame until its current message is sent (for instance, if the majority of a fragmented message is already sent, an endpoint MAY send the remaining fragments before sending a Close frame). However, there is no guarantee that the endpoint that has already sent a Close frame will continue to process data.

如果端点接收到闭合帧并且之前未发送闭合帧,则端点必须发送闭合帧作为响应。(当发送一个闭合帧作为响应时,端点通常会回显它接收到的状态代码。)它应该尽快这样做。端点可以延迟发送结束帧,直到发送其当前消息为止(例如,如果已发送大部分分段消息,则端点可以在发送结束帧之前发送剩余的分段)。但是,无法保证已发送闭合帧的端点将继续处理数据。

After both sending and receiving a Close message, an endpoint considers the WebSocket connection closed and MUST close the underlying TCP connection. The server MUST close the underlying TCP connection immediately; the client SHOULD wait for the server to close the connection but MAY close the connection at any time after sending and receiving a Close message, e.g., if it has not received a TCP Close from the server in a reasonable time period.

在发送和接收关闭消息之后,端点会认为WebSocket连接已关闭,并且必须关闭底层TCP连接。服务器必须立即关闭底层TCP连接;客户端应等待服务器关闭连接,但可以在发送和接收关闭消息后的任何时间关闭连接,例如,如果客户端在合理的时间段内未收到来自服务器的TCP关闭消息。

If a client and server both send a Close message at the same time, both endpoints will have sent and received a Close message and should consider the WebSocket connection closed and close the underlying TCP connection.

如果客户端和服务器同时发送一个关闭消息,则两个端点都会发送和接收一个关闭消息,并且应该考虑WebSoSt连接关闭并关闭底层TCP连接。

5.5.2. Ping
5.5.2. 发出砰的声响

The Ping frame contains an opcode of 0x9.

Ping帧包含一个操作码0x9。

A Ping frame MAY include "Application data".

Ping帧可以包括“应用数据”。

Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response, unless it already received a Close frame. It SHOULD respond with Pong frame as soon as is practical. Pong frames are discussed in Section 5.5.3.

在接收到Ping帧后,端点必须发送Pong帧作为响应,除非它已经接收到闭合帧。只要可行,它应该尽快用Pong帧进行响应。Pong帧在第5.5.3节中讨论。

An endpoint MAY send a Ping frame any time after the connection is established and before the connection is closed.

端点可以在建立连接之后和关闭连接之前的任何时间发送Ping帧。

NOTE: A Ping frame may serve either as a keepalive or as a means to verify that the remote endpoint is still responsive.

注意:Ping帧可以用作keepalive,也可以用作验证远程端点是否仍有响应的手段。

5.5.3. Pong
5.5.3. 庞

The Pong frame contains an opcode of 0xA.

Pong帧包含一个0xA的操作码。

Section 5.5.2 details requirements that apply to both Ping and Pong frames.

第5.5.2节详细说明了适用于乒乓球拍和乒乓球拍的要求。

A Pong frame sent in response to a Ping frame must have identical "Application data" as found in the message body of the Ping frame being replied to.

为响应Ping帧而发送的Pong帧必须具有与被应答的Ping帧的消息体中相同的“应用程序数据”。

If an endpoint receives a Ping frame and has not yet sent Pong frame(s) in response to previous Ping frame(s), the endpoint MAY elect to send a Pong frame for only the most recently processed Ping frame.

如果端点接收到Ping帧并且尚未发送Pong帧以响应先前的Ping帧,则该端点可以选择仅为最近处理的Ping帧发送Pong帧。

A Pong frame MAY be sent unsolicited. This serves as a unidirectional heartbeat. A response to an unsolicited Pong frame is not expected.

Pong帧可以主动发送。这是一个单向心跳。不期望对未经请求的Pong帧做出响应。

5.6. Data Frames
5.6. 数据帧

Data frames (e.g., non-control frames) are identified by opcodes where the most significant bit of the opcode is 0. Currently defined opcodes for data frames include 0x1 (Text), 0x2 (Binary). Opcodes 0x3-0x7 are reserved for further non-control frames yet to be defined.

数据帧(例如,非控制帧)由操作码标识,其中操作码的最高有效位为0。当前定义的数据帧操作码包括0x1(文本)、0x2(二进制)。操作码0x3-0x7保留用于尚未定义的其他非控制帧。

Data frames carry application-layer and/or extension-layer data. The opcode determines the interpretation of the data:

数据帧携带应用层和/或扩展层数据。操作码决定数据的解释:

Text

文本

The "Payload data" is text data encoded as UTF-8. Note that a particular text frame might include a partial UTF-8 sequence; however, the whole message MUST contain valid UTF-8. Invalid UTF-8 in reassembled messages is handled as described in Section 8.1.

“有效负载数据”是编码为UTF-8的文本数据。注意,特定文本框可能包括部分UTF-8序列;但是,整个消息必须包含有效的UTF-8。按照第8.1节所述处理重新组装消息中的无效UTF-8。

Binary

二进制的

The "Payload data" is arbitrary binary data whose interpretation is solely up to the application layer.

“有效载荷数据”是任意二进制数据,其解释完全取决于应用层。

5.7. Examples
5.7. 例子

o A single-frame unmasked text message

o 单帧无掩码文本消息

* 0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains "Hello")

* 0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f(包含“你好”)

o A single-frame masked text message

o 单帧屏蔽文本消息

* 0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (contains "Hello")

* 0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58(包含“你好”)

o A fragmented unmasked text message

o 碎片化的未屏蔽文本消息

* 0x01 0x03 0x48 0x65 0x6c (contains "Hel")

* 0x01 0x03 0x48 0x65 0x6c(包含“Hel”)

* 0x80 0x02 0x6c 0x6f (contains "lo")

* 0x80 0x02 0x6c 0x6f(包含“lo”)

o Unmasked Ping request and masked Ping response

o 未屏蔽的Ping请求和屏蔽的Ping响应

* 0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains a body of "Hello", but the contents of the body are arbitrary)

* 0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f(包含“Hello”的正文,但正文的内容是任意的)

* 0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (contains a body of "Hello", matching the body of the ping)

* 0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58(包含“Hello”主体,与ping主体匹配)

o 256 bytes binary message in a single unmasked frame

o 单个无掩码帧中的256字节二进制消息

* 0x82 0x7E 0x0100 [256 bytes of binary data]

* 0x82 0x7E 0x0100[256字节二进制数据]

o 64KiB binary message in a single unmasked frame

o 单个无掩码帧中的64KiB二进制消息

* 0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]

* 0x82 0x7F 0x0000000000010000[65536字节二进制数据]

5.8. Extensibility
5.8. 扩展性

The protocol is designed to allow for extensions, which will add capabilities to the base protocol. The endpoints of a connection MUST negotiate the use of any extensions during the opening handshake. This specification provides opcodes 0x3 through 0x7 and 0xB through 0xF, the "Extension data" field, and the frame-rsv1, frame-rsv2, and frame-rsv3 bits of the frame header for use by extensions. The negotiation of extensions is discussed in further detail in Section 9.1. Below are some anticipated uses of extensions. This list is neither complete nor prescriptive.

该协议旨在允许扩展,这将为基本协议添加功能。连接的端点必须在开始握手期间协商任何扩展的使用。本规范提供操作码0x3至0x7和0xB至0xF、“扩展数据”字段以及帧头的帧rsv1、帧rsv2和帧rsv3位,供扩展使用。第9.1节将进一步详细讨论延期谈判。下面是扩展的一些预期用途。这份清单既不完整也不规范。

o "Extension data" may be placed in the "Payload data" before the "Application data".

o “扩展数据”可以放在“应用数据”之前的“有效载荷数据”中。

o Reserved bits can be allocated for per-frame needs.

o 可以根据每帧需要分配保留位。

o Reserved opcode values can be defined.

o 可以定义保留的操作码值。

o Reserved bits can be allocated to the opcode field if more opcode values are needed.

o 如果需要更多的操作码值,可以将保留位分配给操作码字段。

o A reserved bit or an "extension" opcode can be defined that allocates additional bits out of the "Payload data" to define larger opcodes or more per-frame bits.

o 可以定义保留位或“扩展”操作码,从“有效负载数据”中分配额外的位,以定义更大的操作码或更多的每帧位。

6. Sending and Receiving Data
6. 发送和接收数据
6.1. Sending Data
6.1. 发送数据

To _Send a WebSocket Message_ comprising of /data/ over a WebSocket connection, an endpoint MUST perform the following steps.

要通过WebSocket连接发送包含/data/的WebSocket消息,端点必须执行以下步骤。

1. The endpoint MUST ensure the WebSocket connection is in the OPEN state (cf. Sections 4.1 and 4.2.2.) If at any point the state of the WebSocket connection changes, the endpoint MUST abort the following steps.

1. 端点必须确保WebSocket连接处于打开状态(参见第4.1节和第4.2.2节)。如果在任何时候WebSocket连接的状态发生变化,端点必须中止以下步骤。

2. An endpoint MUST encapsulate the /data/ in a WebSocket frame as defined in Section 5.2. If the data to be sent is large or if the data is not available in its entirety at the point the endpoint wishes to begin sending the data, the endpoint MAY alternately encapsulate the data in a series of frames as defined in Section 5.4.

2. 端点必须将/data/封装在第5.2节中定义的WebSocket框架中。如果要发送的数据很大,或者如果在端点希望开始发送数据的点上数据不完整,则端点可以按照第5.4节中的定义,交替地将数据封装在一系列帧中。

3. The opcode (frame-opcode) of the first frame containing the data MUST be set to the appropriate value from Section 5.2 for data that is to be interpreted by the recipient as text or binary data.

3. 包含数据的第一帧的操作码(帧操作码)必须设置为第5.2节中的适当值,以便接收方将其解释为文本或二进制数据。

4. The FIN bit (frame-fin) of the last frame containing the data MUST be set to 1 as defined in Section 5.2.

4. 包含数据的最后一帧的FIN位(帧FIN)必须设置为第5.2节中定义的1。

5. If the data is being sent by the client, the frame(s) MUST be masked as defined in Section 5.3.

5. 如果数据由客户端发送,则必须按照第5.3节的规定屏蔽帧。

6. If any extensions (Section 9) have been negotiated for the WebSocket connection, additional considerations may apply as per the definition of those extensions.

6. 如果为WebSocket连接协商了任何扩展(第9节),则可根据这些扩展的定义应用其他注意事项。

7. The frame(s) that have been formed MUST be transmitted over the underlying network connection.

7. 必须通过基础网络连接传输已形成的帧。

6.2. Receiving Data
6.2. 接收数据

To receive WebSocket data, an endpoint listens on the underlying network connection. Incoming data MUST be parsed as WebSocket frames as defined in Section 5.2. If a control frame (Section 5.5) is received, the frame MUST be handled as defined by Section 5.5. Upon receiving a data frame (Section 5.6), the endpoint MUST note the /type/ of the data as defined by the opcode (frame-opcode) from Section 5.2. The "Application data" from this frame is defined as the /data/ of the message. If the frame comprises an unfragmented message (Section 5.4), it is said that _A WebSocket Message Has Been Received_ with type /type/ and data /data/. If the frame is part of a fragmented message, the "Application data" of the subsequent data frames is concatenated to form the /data/. When the last fragment is received as indicated by the FIN bit (frame-fin), it is said that _A WebSocket Message Has Been Received_ with data /data/ (comprised of the concatenation of the "Application data" of the fragments) and

要接收WebSocket数据,端点将侦听基础网络连接。传入数据必须解析为第5.2节中定义的WebSocket帧。如果收到控制框架(第5.5节),必须按照第5.5节的规定处理框架。接收到数据帧(第5.6节)后,端点必须注意第5.2节操作码(帧操作码)定义的数据的/类型/。此框架中的“应用程序数据”定义为消息的/data/。如果帧包含未分段的消息(第5.4节),则表示已收到类型为/type/和数据为/data/的WebSocket消息。如果该帧是分段消息的一部分,则后续数据帧的“应用程序数据”将连接起来以形成/data/。如FIN位(帧FIN)所示,当接收到最后一个片段时,表示已接收到带有数据/数据/(由片段的“应用程序数据”的串联组成)的WebSocket消息,并且

type /type/ (noted from the first frame of the fragmented message). Subsequent data frames MUST be interpreted as belonging to a new WebSocket message.

type/type/(从分段消息的第一帧中注释)。后续数据帧必须解释为属于新的WebSocket消息。

Extensions (Section 9) MAY change the semantics of how data is read, specifically including what comprises a message boundary. Extensions, in addition to adding "Extension data" before the "Application data" in a payload, MAY also modify the "Application data" (such as by compressing it).

扩展(第9节)可能会更改数据读取方式的语义,特别是包含消息边界的内容。除了在有效负载中的“应用程序数据”之前添加“扩展数据”之外,扩展还可以修改“应用程序数据”(例如通过压缩它)。

A server MUST remove masking for data frames received from a client as described in Section 5.3.

如第5.3节所述,服务器必须移除从客户端接收的数据帧的屏蔽。

7. Closing the Connection
7. 关闭连接
7.1. Definitions
7.1. 定义
7.1.1. Close the WebSocket Connection
7.1.1. 关闭WebSocket连接

To _Close the WebSocket Connection_, an endpoint closes the underlying TCP connection. An endpoint SHOULD use a method that cleanly closes the TCP connection, as well as the TLS session, if applicable, discarding any trailing bytes that may have been received. An endpoint MAY close the connection via any means available when necessary, such as when under attack.

要关闭WebSocket连接,端点将关闭底层TCP连接。端点应使用干净地关闭TCP连接以及TLS会话(如果适用)的方法,丢弃可能已接收到的任何尾随字节。端点可以在必要时通过任何可用的方式关闭连接,例如在受到攻击时。

The underlying TCP connection, in most normal cases, SHOULD be closed first by the server, so that it holds the TIME_WAIT state and not the client (as this would prevent it from re-opening the connection for 2 maximum segment lifetimes (2MSL), while there is no corresponding server impact as a TIME_WAIT connection is immediately reopened upon a new SYN with a higher seq number). In abnormal cases (such as not having received a TCP Close from the server after a reasonable amount of time) a client MAY initiate the TCP Close. As such, when a server is instructed to _Close the WebSocket Connection_ it SHOULD initiate a TCP Close immediately, and when a client is instructed to do the same, it SHOULD wait for a TCP Close from the server.

在大多数正常情况下,底层TCP连接应该首先由服务器关闭,以便它保持TIME_WAIT状态,而不是客户端(因为这将阻止它在2个最大段生存期(2MSL)内重新打开连接),但没有相应的服务器影响,因为一个具有更高序号的新SYN会立即重新打开TIME_WAIT连接)。在异常情况下(例如,在合理的时间后没有从服务器接收到TCP关闭),客户机可能会启动TCP关闭。因此,当服务器被指示关闭WebSocket连接时,它应该立即启动TCP关闭,当客户端被指示执行相同操作时,它应该等待服务器的TCP关闭。

As an example of how to obtain a clean closure in C using Berkeley sockets, one would call shutdown() with SHUT_WR on the socket, call recv() until obtaining a return value of 0 indicating that the peer has also performed an orderly shutdown, and finally call close() on the socket.

作为如何使用Berkeley套接字在C中获得干净闭包的示例,可以使用套接字上的shutdown_WR调用shutdown(),调用recv(),直到获得返回值0,表示对等方也执行了有序闭包,最后在套接字上调用close()。

7.1.2. Start the WebSocket Closing Handshake
7.1.2. 开始WebSocket关闭握手

To _Start the WebSocket Closing Handshake_ with a status code (Section 7.4) /code/ and an optional close reason (Section 7.1.6) /reason/, an endpoint MUST send a Close control frame, as described in Section 5.5.1, whose status code is set to /code/ and whose close reason is set to /reason/. Once an endpoint has both sent and received a Close control frame, that endpoint SHOULD _Close the WebSocket Connection_ as defined in Section 7.1.1.

要使用状态代码(第7.4节)/code/和可选关闭原因(第7.1.6节)/reason/启动WebSocket关闭握手,端点必须发送关闭控制框,如第5.5.1节所述,其状态代码设置为/code/,关闭原因设置为/reason/。一旦一个端点发送和接收到关闭控制帧,该端点应_关闭第7.1.1节中定义的WebSocket连接。

7.1.3. The WebSocket Closing Handshake is Started
7.1.3. 开始WebSocket关闭握手

Upon either sending or receiving a Close control frame, it is said that _The WebSocket Closing Handshake is Started_ and that the WebSocket connection is in the CLOSING state.

在发送或接收到关闭控制帧时,表示“WebSocket关闭握手已开始”,并且WebSocket连接处于关闭状态。

7.1.4. The WebSocket Connection is Closed
7.1.4. WebSocket连接已关闭

When the underlying TCP connection is closed, it is said that _The WebSocket Connection is Closed_ and that the WebSocket connection is in the CLOSED state. If the TCP connection was closed after the WebSocket closing handshake was completed, the WebSocket connection is said to have been closed _cleanly_.

当底层TCP连接关闭时,表示_WebSocket连接已关闭u且WebSocket连接处于关闭状态。如果TCP连接在WebSocket关闭握手完成后关闭,则称WebSocket连接已完全关闭。

If the WebSocket connection could not be established, it is also said that _The WebSocket Connection is Closed_, but not _cleanly_.

如果无法建立WebSocket连接,也可以说_WebSocket连接已关闭u,但未完全关闭u。

7.1.5. The WebSocket Connection Close Code
7.1.5. WebSocket连接关闭代码

As defined in Sections 5.5.1 and 7.4, a Close control frame may contain a status code indicating a reason for closure. A closing of the WebSocket connection may be initiated by either endpoint, potentially simultaneously. _The WebSocket Connection Close Code_ is defined as the status code (Section 7.4) contained in the first Close control frame received by the application implementing this protocol. If this Close control frame contains no status code, _The WebSocket Connection Close Code_ is considered to be 1005. If _The WebSocket Connection is Closed_ and no Close control frame was received by the endpoint (such as could occur if the underlying transport connection is lost), _The WebSocket Connection Close Code_ is considered to be 1006.

如第5.5.1节和第7.4节所述,关闭控制框架可能包含指示关闭原因的状态代码。WebSocket连接的关闭可能由任一端点启动,可能同时启动_WebSocket连接关闭代码uu定义为执行此协议的应用程序接收到的第一个关闭控制帧中包含的状态代码(第7.4节)。如果此关闭控制框不包含状态代码,则WebSocket连接关闭代码被视为1005。如果_WebSocket连接已关闭u且端点未接收到关闭控制帧(例如,如果基础传输连接丢失,则可能发生这种情况),_WebSocket连接关闭代码u被视为1006。

NOTE: Two endpoints may not agree on the value of _The WebSocket Connection Close Code_. As an example, if the remote endpoint sent a Close frame but the local application has not yet read the data containing the Close frame from its socket's receive buffer, and the local application independently decided to close the connection and send a Close frame, both endpoints will have sent and received a

注意:两个端点可能对WebSocket连接关闭代码的值不一致。例如,如果远程端点发送闭合帧,但本地应用程序尚未从其套接字的接收缓冲区读取包含闭合帧的数据,并且本地应用程序独立决定关闭连接并发送闭合帧,则两个端点都将发送和接收闭合帧

Close frame and will not send further Close frames. Each endpoint will see the status code sent by the other end as _The WebSocket Connection Close Code_. As such, it is possible that the two endpoints may not agree on the value of _The WebSocket Connection Close Code_ in the case that both endpoints _Start the WebSocket Closing Handshake_ independently and at roughly the same time.

关闭帧,将不会再发送关闭帧。每个端点将看到由另一端发送的状态代码,即WebSocket连接关闭代码。因此,在两个端点独立且大致同时启动WebSocket关闭握手的情况下,两个端点可能在WebSocket连接关闭代码的值上不一致。

7.1.6. The WebSocket Connection Close Reason
7.1.6. WebSocket连接关闭原因

As defined in Sections 5.5.1 and 7.4, a Close control frame may contain a status code indicating a reason for closure, followed by UTF-8-encoded data, the interpretation of said data being left to the endpoints and not defined by this protocol. A closing of the WebSocket connection may be initiated by either endpoint, potentially simultaneously. _The WebSocket Connection Close Reason_ is defined as the UTF-8-encoded data following the status code (Section 7.4) contained in the first Close control frame received by the application implementing this protocol. If there is no such data in the Close control frame, _The WebSocket Connection Close Reason_ is the empty string.

如第5.5.1节和第7.4节所定义,关闭控制框架可能包含一个状态代码,指示关闭原因,然后是UTF-8编码的数据,所述数据的解释留给端点,不由本协议定义。WebSocket连接的关闭可能由任一端点启动,可能同时启动_WebSocket连接关闭原因被定义为UTF-8编码的数据,该数据位于实现该协议的应用程序接收到的第一个关闭控制帧中包含的状态代码(第7.4节)之后。如果关闭控制框中没有此类数据,则WebSocket连接关闭原因为空字符串。

NOTE: Following the same logic as noted in Section 7.1.5, two endpoints may not agree on _The WebSocket Connection Close Reason_.

注:按照第7.1.5节所述的相同逻辑,两个端点可能不同意WebSocket连接关闭原因。

7.1.7. Fail the WebSocket Connection
7.1.7. 使WebSocket连接失败

Certain algorithms and specifications require an endpoint to _Fail the WebSocket Connection_. To do so, the client MUST _Close the WebSocket Connection_, and MAY report the problem to the user (which would be especially useful for developers) in an appropriate manner. Similarly, to do so, the server MUST _Close the WebSocket Connection_, and SHOULD log the problem.

某些算法和规范需要一个端点来使WebSocket连接失败。为此,客户端必须关闭WebSocket连接,并以适当的方式向用户报告问题(这对开发人员特别有用)。同样,要这样做,服务器必须关闭WebSocket连接,并记录问题。

If _The WebSocket Connection is Established_ prior to the point where the endpoint is required to _Fail the WebSocket Connection_, the endpoint SHOULD send a Close frame with an appropriate status code (Section 7.4) before proceeding to _Close the WebSocket Connection_. An endpoint MAY omit sending a Close frame if it believes the other side is unlikely to be able to receive and process the Close frame, due to the nature of the error that led the WebSocket connection to fail in the first place. An endpoint MUST NOT continue to attempt to process data (including a responding Close frame) from the remote endpoint after being instructed to _Fail the WebSocket Connection_.

如果在要求端点使WebSocket连接失败的点之前建立了WebSocket连接,则在继续关闭WebSocket连接之前,端点应发送带有适当状态代码的关闭帧(第7.4节)。如果由于导致WebSocket连接首先失败的错误的性质,端点认为另一方不太可能接收和处理闭合帧,则可以忽略发送闭合帧。在被指示“WebSocket连接失败”后,终结点不得继续尝试处理来自远程终结点的数据(包括响应关闭帧)。

Except as indicated above or as specified by the application layer (e.g., a script using the WebSocket API), clients SHOULD NOT close the connection.

除上述说明或应用层指定(例如,使用WebSocket API的脚本)外,客户端不应关闭连接。

7.2. Abnormal Closures
7.2. 异常关闭
7.2.1. Client-Initiated Closure
7.2.1. 客户端启动的关闭

Certain algorithms, in particular during the opening handshake, require the client to _Fail the WebSocket Connection_. To do so, the client MUST _Fail the WebSocket Connection_ as defined in Section 7.1.7.

某些算法,特别是在开始握手时,要求客户端使WebSocket连接失败。为此,客户端必须按照第7.1.7节的定义,使WebSocket连接失败。

If at any point the underlying transport layer connection is unexpectedly lost, the client MUST _Fail the WebSocket Connection_.

如果在任何时候底层传输层连接意外丢失,客户端必须使WebSocket连接失败。

Except as indicated above or as specified by the application layer (e.g., a script using the WebSocket API), clients SHOULD NOT close the connection.

除上述说明或应用层指定(例如,使用WebSocket API的脚本)外,客户端不应关闭连接。

7.2.2. Server-Initiated Closure
7.2.2. 服务器启动的关闭

Certain algorithms require or recommend that the server _Abort the WebSocket Connection_ during the opening handshake. To do so, the server MUST simply _Close the WebSocket Connection_ (Section 7.1.1).

某些算法要求或建议服务器在开始握手时中止WebSocket连接。为此,服务器必须简单地关闭WebSocket连接(第7.1.1节)。

7.2.3. Recovering from Abnormal Closure
7.2.3. 从异常关闭中恢复

Abnormal closures may be caused by any number of reasons. Such closures could be the result of a transient error, in which case reconnecting may lead to a good connection and a resumption of normal operations. Such closures may also be the result of a nontransient problem, in which case if each deployed client experiences an abnormal closure and immediately and persistently tries to reconnect, the server may experience what amounts to a denial-of-service attack by a large number of clients trying to reconnect. The end result of such a scenario could be that the service is unable to recover in a timely manner or recovery is made much more difficult.

异常关闭可能由多种原因引起。这种关闭可能是暂时性错误的结果,在这种情况下,重新连接可能导致良好连接并恢复正常操作。此类关闭也可能是非暂时性问题的结果,在这种情况下,如果每个部署的客户端都遇到异常关闭并立即持续尝试重新连接,服务器可能会遇到大量试图重新连接的客户端的拒绝服务攻击。这种情况的最终结果可能是服务无法及时恢复,或者恢复变得更加困难。

To prevent this, clients SHOULD use some form of backoff when trying to reconnect after abnormal closures as described in this section.

为了防止出现这种情况,客户机在异常关闭后尝试重新连接时,应使用某种形式的回退,如本节所述。

The first reconnect attempt SHOULD be delayed by a random amount of time. The parameters by which this random delay is chosen are left to the client to decide; a value chosen randomly between 0 and 5 seconds is a reasonable initial delay though clients MAY choose a different interval from which to select a delay length based on implementation experience and particular application.

第一次重新连接尝试应延迟随机时间。选择随机延迟的参数留给客户决定;在0到5秒之间随机选择的值是一个合理的初始延迟,尽管客户端可以根据实现经验和特定应用程序选择不同的间隔来选择延迟长度。

Should the first reconnect attempt fail, subsequent reconnect attempts SHOULD be delayed by increasingly longer amounts of time, using a method such as truncated binary exponential backoff.

如果第一次重新连接尝试失败,后续重新连接尝试应使用截断二进制指数退避等方法延迟越来越长的时间。

7.3. Normal Closure of Connections
7.3. 正常关闭连接

Servers MAY close the WebSocket connection whenever desired. Clients SHOULD NOT close the WebSocket connection arbitrarily. In either case, an endpoint initiates a closure by following the procedures to _Start the WebSocket Closing Handshake_ (Section 7.1.2).

服务器可以在需要时关闭WebSocket连接。客户端不应随意关闭WebSocket连接。在任何一种情况下,端点都会通过以下步骤启动关闭WebSocket关闭握手(第7.1.2节)。

7.4. Status Codes
7.4. 状态代码

When closing an established connection (e.g., when sending a Close frame, after the opening handshake has completed), an endpoint MAY indicate a reason for closure. The interpretation of this reason by an endpoint, and the action an endpoint should take given this reason, are left undefined by this specification. This specification defines a set of pre-defined status codes and specifies which ranges may be used by extensions, frameworks, and end applications. The status code and any associated textual message are optional components of a Close frame.

当关闭已建立的连接时(例如,当发送关闭帧时,在开始握手完成之后),端点可以指示关闭的原因。本规范未定义端点对此原因的解释以及端点基于此原因应采取的操作。本规范定义了一组预定义的状态代码,并指定了扩展、框架和最终应用程序可以使用的范围。状态代码和任何相关文本消息都是闭合帧的可选组件。

7.4.1. Defined Status Codes
7.4.1. 定义的状态代码

Endpoints MAY use the following pre-defined status codes when sending a Close frame.

端点在发送闭合帧时可以使用以下预定义的状态代码。

1000

1000

1000 indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled.

1000表示正常关闭,意味着建立连接的目的已经实现。

1001

1001

1001 indicates that an endpoint is "going away", such as a server going down or a browser having navigated away from a page.

1001表示端点正在“离开”,例如服务器正在关闭或浏览器已经离开页面。

1002

1002

1002 indicates that an endpoint is terminating the connection due to a protocol error.

1002表示端点由于协议错误而终止连接。

1003

1003

1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message).

1003表示端点正在终止连接,因为它已接收到无法接受的数据类型(例如,仅理解文本数据的端点在接收到二进制消息时可能会发送此数据)。

1004

1004

Reserved. The specific meaning might be defined in the future.

保留的。具体含义可能在将来确定。

1005

1005

1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting a status code to indicate that no status code was actually present.

1005是保留值,端点不得将其设置为关闭控制帧中的状态代码。它被指定用于希望状态代码指示实际不存在状态代码的应用程序中。

1006

1006

1006 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting a status code to indicate that the connection was closed abnormally, e.g., without sending or receiving a Close control frame.

1006是保留值,端点不得将其设置为关闭控制帧中的状态代码。它被指定用于希望状态代码指示连接异常关闭的应用程序中,例如,未发送或接收关闭控制帧。

1007

1007

1007 indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [RFC3629] data within a text message).

1007表示端点正在终止连接,因为它在消息中接收到与消息类型不一致的数据(例如,文本消息中的非UTF-8[RFC3629]数据)。

1008

1008

1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the policy.

1008表示端点正在终止连接,因为它收到了违反其策略的消息。这是一个通用状态代码,当没有其他更合适的状态代码(如1003或1009)或需要隐藏有关策略的特定详细信息时,可以返回该代码。

1009

1009

1009 indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process.

1009表示端点正在终止连接,因为它接收到的消息太大,无法处理。

1010

1010

1010 indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. The list of extensions that

1010表示端点(客户端)正在终止连接,因为它期望服务器协商一个或多个扩展,但服务器没有在WebSocket握手的响应消息中返回这些扩展。该扩展的列表

are needed SHOULD appear in the /reason/ part of the Close frame. Note that this status code is not used by the server, because it can fail the WebSocket handshake instead.

是否需要显示在结束框的/原因/部分。请注意,服务器不使用此状态代码,因为它可能导致WebSocket握手失败。

1011

1011

1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.

1011表示服务器正在终止连接,因为它遇到了阻止其完成请求的意外情况。

1015

1015

1015 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting a status code to indicate that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).

1015是保留值,端点不得将其设置为闭合控制帧中的状态代码。它被指定用于需要状态代码的应用程序中,该代码指示由于未能执行TLS握手而关闭的连接(例如,无法验证服务器证书)。

7.4.2. Reserved Status Code Ranges
7.4.2. 保留状态代码范围

0-999

0-999

Status codes in the range 0-999 are not used.

不使用0-999范围内的状态代码。

1000-2999

1000-2999

Status codes in the range 1000-2999 are reserved for definition by this protocol, its future revisions, and extensions specified in a permanent and readily available public specification.

1000-2999范围内的状态代码保留供本协议定义,其未来修订版和永久性且随时可用的公共规范中规定的扩展。

3000-3999

3000-3999

Status codes in the range 3000-3999 are reserved for use by libraries, frameworks, and applications. These status codes are registered directly with IANA. The interpretation of these codes is undefined by this protocol.

3000-3999范围内的状态代码保留供库、框架和应用程序使用。这些状态代码直接向IANA注册。本协议未定义这些代码的解释。

4000-4999

4000-4999

Status codes in the range 4000-4999 are reserved for private use and thus can't be registered. Such codes can be used by prior agreements between WebSocket applications. The interpretation of these codes is undefined by this protocol.

4000-4999范围内的状态代码保留供私人使用,因此无法注册。此类代码可由WebSocket应用程序之间的事先协议使用。本协议未定义这些代码的解释。

8. Error Handling
8. 错误处理
8.1. Handling Errors in UTF-8-Encoded Data
8.1. UTF-8编码数据中的错误处理

When an endpoint is to interpret a byte stream as UTF-8 but finds that the byte stream is not, in fact, a valid UTF-8 stream, that endpoint MUST _Fail the WebSocket Connection_. This rule applies both during the opening handshake and during subsequent data exchange.

当端点将字节流解释为UTF-8,但发现该字节流实际上不是有效的UTF-8流时,该端点必须使WebSocket连接失败。此规则在开始握手和随后的数据交换期间都适用。

9. Extensions
9. 扩展

WebSocket clients MAY request extensions to this specification, and WebSocket servers MAY accept some or all extensions requested by the client. A server MUST NOT respond with any extension not requested by the client. If extension parameters are included in negotiations between the client and the server, those parameters MUST be chosen in accordance with the specification of the extension to which the parameters apply.

WebSocket客户端可能会请求对此规范的扩展,WebSocket服务器可能会接受客户端请求的部分或全部扩展。服务器不得响应客户端未请求的任何扩展。如果扩展参数包括在客户端和服务器之间的协商中,则必须根据参数适用的扩展规范选择这些参数。

9.1. Negotiating Extensions
9.1. 谈判延期

A client requests extensions by including a |Sec-WebSocket-Extensions| header field, which follows the normal rules for HTTP header fields (see [RFC2616], Section 4.2) and the value of the header field is defined by the following ABNF [RFC2616]. Note that this section is using ABNF syntax/rules from [RFC2616], including the "implied *LWS rule". If a value is received by either the client or the server during negotiation that does not conform to the ABNF below, the recipient of such malformed data MUST immediately _Fail the WebSocket Connection_.

客户端通过包含| Sec WebSocket extensions |头字段请求扩展,该字段遵循HTTP头字段的正常规则(请参见[RFC2616],第4.2节),头字段的值由以下ABNF[RFC2616]定义。注意,本节使用[RFC2616]中的ABNF语法/规则,包括“隐含的*LWS规则”。如果客户机或服务器在协商期间接收到不符合以下ABNF的值,则此类格式错误数据的收件人必须立即使WebSocket连接失败。

         Sec-WebSocket-Extensions = extension-list
         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.
        
         Sec-WebSocket-Extensions = extension-list
         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.
        

Note that like other HTTP header fields, this header field MAY be split or combined across multiple lines. Ergo, the following are equivalent:

请注意,与其他HTTP头字段一样,此头字段可以跨多行拆分或组合。因此,以下是等效的:

         Sec-WebSocket-Extensions: foo
         Sec-WebSocket-Extensions: bar; baz=2
        
         Sec-WebSocket-Extensions: foo
         Sec-WebSocket-Extensions: bar; baz=2
        

is exactly equivalent to

完全等同于

         Sec-WebSocket-Extensions: foo, bar; baz=2
        
         Sec-WebSocket-Extensions: foo, bar; baz=2
        

Any extension-token used MUST be a registered token (see Section 11.4). The parameters supplied with any given extension MUST be defined for that extension. Note that the client is only offering to use any advertised extensions and MUST NOT use them unless the server indicates that it wishes to use the extension.

使用的任何扩展令牌必须是注册令牌(见第11.4节)。必须为该扩展定义随任何给定扩展提供的参数。请注意,客户机仅提供使用任何播发的扩展,除非服务器指示它希望使用扩展,否则不得使用这些扩展。

Note that the order of extensions is significant. Any interactions between multiple extensions MAY be defined in the documents defining the extensions. In the absence of such definitions, the interpretation is that the header fields listed by the client in its request represent a preference of the header fields it wishes to use, with the first options listed being most preferable. The extensions listed by the server in response represent the extensions actually in use for the connection. Should the extensions modify the data and/or framing, the order of operations on the data should be assumed to be the same as the order in which the extensions are listed in the server's response in the opening handshake.

请注意,扩展的顺序很重要。多个扩展之间的任何交互都可以在定义扩展的文档中定义。在没有此类定义的情况下,解释为客户机在其请求中列出的头字段表示其希望使用的头字段的首选项,其中列出的第一个选项是最优选的。服务器在响应中列出的扩展代表实际用于连接的扩展。如果扩展修改了数据和/或帧,则应假定对数据的操作顺序与在开始握手时服务器响应中列出扩展的顺序相同。

For example, if there are two extensions "foo" and "bar" and if the header field |Sec-WebSocket-Extensions| sent by the server has the value "foo, bar", then operations on the data will be made as bar(foo(data)), be those changes to the data itself (such as compression) or changes to the framing that may "stack".

例如,如果有两个扩展名“foo”和“bar”,并且如果服务器发送的标题字段| Sec WebSocket extensions |具有值“foo,bar”,则对数据的操作将作为bar(foo(data))进行,即对数据本身的更改(例如压缩)或对帧的更改可能是“堆栈”。

Non-normative examples of acceptable extension header fields (note that long lines are folded for readability):

可接受的扩展标题字段的非规范性示例(请注意,为便于阅读,长行被折叠):

         Sec-WebSocket-Extensions: deflate-stream
         Sec-WebSocket-Extensions: mux; max-channels=4; flow-control,
          deflate-stream
         Sec-WebSocket-Extensions: private-extension
        
         Sec-WebSocket-Extensions: deflate-stream
         Sec-WebSocket-Extensions: mux; max-channels=4; flow-control,
          deflate-stream
         Sec-WebSocket-Extensions: private-extension
        

A server accepts one or more extensions by including a |Sec-WebSocket-Extensions| header field containing one or more extensions that were requested by the client. The interpretation of

服务器通过包含| Sec WebSocket extensions |头字段(包含客户端请求的一个或多个扩展)来接受一个或多个扩展。解读

any extension parameters, and what constitutes a valid response by a server to a requested set of parameters by a client, will be defined by each such extension.

任何扩展参数,以及服务器对客户端请求的一组参数的有效响应,都将由每个此类扩展定义。

9.2. Known Extensions
9.2. 已知扩展

Extensions provide a mechanism for implementations to opt-in to additional protocol features. This document doesn't define any extension, but implementations MAY use extensions defined separately.

扩展为实现提供了一种选择附加协议功能的机制。本文档没有定义任何扩展,但实现可以使用单独定义的扩展。

10. Security Considerations
10. 安全考虑

This section describes some security considerations applicable to the WebSocket Protocol. Specific security considerations are described in subsections of this section.

本节介绍适用于WebSocket协议的一些安全注意事项。本节各小节介绍了具体的安全注意事项。

10.1. Non-Browser Clients
10.1. 非浏览器客户端

The WebSocket Protocol protects against malicious JavaScript running inside a trusted application such as a web browser, for example, by checking of the |Origin| header field (see below). See Section 1.6 for additional details. Such assumptions don't hold true in the case of a more-capable client.

WebSocket协议通过检查| Origin | header字段(见下文)等方式保护受信任应用程序(如web浏览器)内运行的恶意JavaScript。更多详情见第1.6节。对于能力更强的客户来说,这些假设并不成立。

While this protocol is intended to be used by scripts in web pages, it can also be used directly by hosts. Such hosts are acting on their own behalf and can therefore send fake |Origin| header fields, misleading the server. Servers should therefore be careful about assuming that they are talking directly to scripts from known origins and must consider that they might be accessed in unexpected ways. In particular, a server should not trust that any input is valid.

虽然此协议旨在由网页中的脚本使用,但也可以由主机直接使用。这样的主机代表自己行事,因此可以发送虚假的| Origin |头字段,误导服务器。因此,服务器应该谨慎地假设他们正直接从已知的源代码中进行对话,并且必须考虑到它们可能以意想不到的方式访问。特别是,服务器不应该相信任何输入都是有效的。

EXAMPLE: If the server uses input as part of SQL queries, all input text should be escaped before being passed to the SQL server, lest the server be susceptible to SQL injection.

示例:如果服务器使用输入作为SQL查询的一部分,则在将所有输入文本传递到SQL server之前,应先对其进行转义,以免服务器易受SQL注入的影响。

10.2. Origin Considerations
10.2. 原产地考虑

Servers that are not intended to process input from any web page but only for certain sites SHOULD verify the |Origin| field is an origin they expect. If the origin indicated is unacceptable to the server, then it SHOULD respond to the WebSocket handshake with a reply containing HTTP 403 Forbidden status code.

不打算处理来自任何网页的输入,但仅针对某些站点的服务器应验证| Origin |字段是否为他们期望的来源。如果服务器无法接受所指示的来源,则它应使用包含HTTP 403禁止状态代码的回复来响应WebSocket握手。

The |Origin| header field protects from the attack cases when the untrusted party is typically the author of a JavaScript application that is executing in the context of the trusted client. The client itself can contact the server and, via the mechanism of the |Origin|

当不受信任方通常是在受信任客户端上下文中执行的JavaScript应用程序的作者时,| Origin | header字段可防止受到攻击。客户机本身可以通过| Origin的机制与服务器联系|

header field, determine whether to extend those communication privileges to the JavaScript application. The intent is not to prevent non-browsers from establishing connections but rather to ensure that trusted browsers under the control of potentially malicious JavaScript cannot fake a WebSocket handshake.

header字段,确定是否将这些通信权限扩展到JavaScript应用程序。其目的不是阻止非浏览器建立连接,而是确保受潜在恶意JavaScript控制的可信浏览器不能伪造WebSocket握手。

10.3. Attacks On Infrastructure (Masking)
10.3. 对基础设施的攻击(屏蔽)

In addition to endpoints being the target of attacks via WebSockets, other parts of web infrastructure, such as proxies, may be the subject of an attack.

除了端点是通过WebSocket进行攻击的目标之外,web基础设施的其他部分(如代理)也可能是攻击的对象。

As this protocol was being developed, an experiment was conducted to demonstrate a class of attacks on proxies that led to the poisoning of caching proxies deployed in the wild [TALKING]. The general form of the attack was to establish a connection to a server under the "attacker's" control, perform an UPGRADE on the HTTP connection similar to what the WebSocket Protocol does to establish a connection, and subsequently send data over that UPGRADEd connection that looked like a GET request for a specific known resource (which in an attack would likely be something like a widely deployed script for tracking hits or a resource on an ad-serving network). The remote server would respond with something that looked like a response to the fake GET request, and this response would be cached by a nonzero percentage of deployed intermediaries, thus poisoning the cache. The net effect of this attack would be that if a user could be convinced to visit a website the attacker controlled, the attacker could potentially poison the cache for that user and other users behind the same cache and run malicious script on other origins, compromising the web security model.

在开发此协议的过程中,进行了一项实验,以演示对代理的一类攻击,这些攻击导致在野外部署的缓存代理中毒[TALKING]。攻击的一般形式是建立到“攻击者”控制下的服务器的连接,在HTTP连接上执行升级,类似于WebSocket协议建立连接所做的操作,然后通过升级后的连接发送数据,该连接看起来像对特定已知资源的GET请求(在攻击中,这可能类似于广泛部署的跟踪点击的脚本或广告服务网络上的资源)。远程服务器将以类似于对伪GET请求的响应的方式进行响应,并且此响应将由非零百分比的已部署中介缓存,从而毒害缓存。此攻击的净效果是,如果用户被说服访问攻击者控制的网站,攻击者可能会可能会毒害该用户和同一缓存后面的其他用户的缓存,并在其他来源上运行恶意脚本,从而损害web安全模型。

To avoid such attacks on deployed intermediaries, it is not sufficient to prefix application-supplied data with framing that is not compliant with HTTP, as it is not possible to exhaustively discover and test that each nonconformant intermediary does not skip such non-HTTP framing and act incorrectly on the frame payload. Thus, the defense adopted is to mask all data from the client to the server, so that the remote script (attacker) does not have control over how the data being sent appears on the wire and thus cannot construct a message that could be misinterpreted by an intermediary as an HTTP request.

为了避免对已部署的中介体进行此类攻击,仅为应用程序提供的数据加上不符合HTTP的帧前缀是不够的,因为不可能彻底发现和测试每个不符合HTTP的中介体是否没有跳过此类非HTTP帧并对帧有效负载做出错误的操作。因此,所采取的防御措施是屏蔽从客户端到服务器的所有数据,以便远程脚本(攻击者)无法控制正在发送的数据在线路上的显示方式,从而无法构造一条消息,该消息可能被中介误认为是HTTP请求。

Clients MUST choose a new masking key for each frame, using an algorithm that cannot be predicted by end applications that provide data. For example, each masking could be drawn from a cryptographically strong random number generator. If the same key is used or a decipherable pattern exists for how the next key is chosen, the attacker can send a message that, when masked, could appear to be

客户端必须为每个帧选择一个新的屏蔽密钥,使用的算法无法由提供数据的终端应用程序预测。例如,每个掩蔽可以从加密强随机数生成器中提取。如果使用了相同的密钥,或者下一个密钥的选择方式存在可解密模式,则攻击者可以发送一条消息,该消息在被屏蔽时可能看起来是

an HTTP request (by taking the message the attacker wishes to see on the wire and masking it with the next masking key to be used, the masking key will effectively unmask the data when the client applies it).

HTTP请求(通过获取攻击者希望在线路上看到的消息并使用下一个要使用的屏蔽密钥对其进行屏蔽,当客户端应用该屏蔽密钥时,该屏蔽密钥将有效地解除对数据的屏蔽)。

It is also necessary that once the transmission of a frame from a client has begun, the payload (application-supplied data) of that frame must not be capable of being modified by the application. Otherwise, an attacker could send a long frame where the initial data was a known value (such as all zeros), compute the masking key being used upon receipt of the first part of the data, and then modify the data that is yet to be sent in the frame to appear as an HTTP request when masked. (This is essentially the same problem described in the previous paragraph with using a known or predictable masking key.) If additional data is to be sent or data to be sent is somehow changed, that new or changed data must be sent in a new frame and thus with a new masking key. In short, once transmission of a frame begins, the contents must not be modifiable by the remote script (application).

还有必要的是,一旦开始从客户端传输帧,该帧的有效载荷(应用程序提供的数据)就不能被应用程序修改。否则,攻击者可能会发送一个长帧,其中初始数据为已知值(如全零),在收到数据的第一部分时计算正在使用的屏蔽密钥,然后修改帧中尚未发送的数据,使其在屏蔽时显示为HTTP请求。(这基本上与上一段中描述的使用已知或可预测屏蔽密钥的问题相同。)如果要发送额外数据或要发送的数据以某种方式发生更改,则必须在新帧中发送新的或更改的数据,从而使用新的屏蔽密钥。简而言之,一旦开始传输帧,远程脚本(应用程序)就不能修改内容。

The threat model being protected against is one in which the client sends data that appears to be an HTTP request. As such, the channel that needs to be masked is the data from the client to the server. The data from the server to the client can be made to look like a response, but to accomplish this request, the client must also be able to forge a request. As such, it was not deemed necessary to mask data in both directions (the data from the server to the client is not masked).

受保护的威胁模型是客户端发送看似HTTP请求的数据的模型。因此,需要屏蔽的通道是从客户端到服务器的数据。从服务器到客户机的数据可以看起来像一个响应,但是为了完成这个请求,客户机还必须能够伪造一个请求。因此,认为没有必要在两个方向上屏蔽数据(从服务器到客户端的数据不被屏蔽)。

Despite the protection provided by masking, non-compliant HTTP proxies will still be vulnerable to poisoning attacks of this type by clients and servers that do not apply masking.

尽管屏蔽提供了保护,但不兼容的HTTP代理仍然容易受到不应用屏蔽的客户端和服务器的此类中毒攻击。

10.4. Implementation-Specific Limits
10.4. 具体实施限制

Implementations that have implementation- and/or platform-specific limitations regarding the frame size or total message size after reassembly from multiple frames MUST protect themselves against exceeding those limits. (For example, a malicious endpoint can try to exhaust its peer's memory or mount a denial-of-service attack by sending either a single big frame (e.g., of size 2**60) or by sending a long stream of small frames that are a part of a fragmented message.) Such an implementation SHOULD impose a limit on frame sizes and the total message size after reassembly from multiple frames.

在从多个帧重新组装后,对于帧大小或消息总大小有实现和/或平台特定限制的实现必须保护自己不超过这些限制。(例如,恶意端点可以通过发送单个大帧(例如,大小为2**60)或发送作为碎片消息一部分的长流小帧,试图耗尽对等方的内存或发起拒绝服务攻击。)这样的实现应该对帧大小和从多个帧重新组装后的总消息大小施加限制。

10.5. WebSocket Client Authentication
10.5. WebSocket客户端身份验证

This protocol doesn't prescribe any particular way that servers can authenticate clients during the WebSocket handshake. The WebSocket server can use any client authentication mechanism available to a generic HTTP server, such as cookies, HTTP authentication, or TLS authentication.

该协议没有规定服务器在WebSocket握手期间对客户端进行身份验证的任何特定方式。WebSocket服务器可以使用通用HTTP服务器可用的任何客户端身份验证机制,如cookie、HTTP身份验证或TLS身份验证。

10.6. Connection Confidentiality and Integrity
10.6. 连接机密性和完整性

Connection confidentiality and integrity is provided by running the WebSocket Protocol over TLS (wss URIs). WebSocket implementations MUST support TLS and SHOULD employ it when communicating with their peers.

通过在TLS上运行WebSocket协议(wss URI),可以提供连接机密性和完整性。WebSocket实现必须支持TLS,并且在与对等方通信时应使用TLS。

For connections using TLS, the amount of benefit provided by TLS depends greatly on the strength of the algorithms negotiated during the TLS handshake. For example, some TLS cipher mechanisms don't provide connection confidentiality. To achieve reasonable levels of protection, clients should use only Strong TLS algorithms. "Web Security Context: User Interface Guidelines" [W3C.REC-wsc-ui-20100812] discusses what constitutes Strong TLS algorithms. [RFC5246] provides additional guidance in Appendix A.5 and Appendix D.3.

对于使用TLS的连接,TLS提供的好处在很大程度上取决于TLS握手期间协商的算法的强度。例如,某些TLS密码机制不提供连接机密性。要实现合理的保护级别,客户端应仅使用强TLS算法。“Web安全上下文:用户界面指南”[W3C.REC-wsc-ui-20100812]讨论了强TLS算法的构成。[RFC5246]在附录A.5和附录D.3中提供了附加指南。

10.7. Handling of Invalid Data
10.7. 无效数据的处理

Incoming data MUST always be validated by both clients and servers. If, at any time, an endpoint is faced with data that it does not understand or that violates some criteria by which the endpoint determines safety of input, or when the endpoint sees an opening handshake that does not correspond to the values it is expecting (e.g., incorrect path or origin in the client request), the endpoint MAY drop the TCP connection. If the invalid data was received after a successful WebSocket handshake, the endpoint SHOULD send a Close frame with an appropriate status code (Section 7.4) before proceeding to _Close the WebSocket Connection_. Use of a Close frame with an appropriate status code can help in diagnosing the problem. If the invalid data is sent during the WebSocket handshake, the server SHOULD return an appropriate HTTP [RFC2616] status code.

传入数据必须始终由客户端和服务器验证。如果在任何时候,一个端点遇到它不理解的数据,或者该数据违反了该端点确定输入安全性的一些标准,或者当该端点看到一个与其期望值不一致的开始握手时(例如,客户端请求中的不正确路径或来源),端点可能会断开TCP连接。如果在成功的WebSocket握手后接收到无效数据,则端点应在继续关闭WebSocket连接之前发送一个带有适当状态代码的关闭帧(第7.4节)。使用带有适当状态代码的闭合机架有助于诊断故障。如果在WebSocket握手期间发送了无效数据,则服务器应返回适当的HTTP[RFC2616]状态代码。

A common class of security problems arises when sending text data using the wrong encoding. This protocol specifies that messages with a Text data type (as opposed to Binary or other types) contain UTF-8- encoded data. Although the length is still indicated and applications implementing this protocol should use the length to determine where the frame actually ends, sending data in an improper

当使用错误的编码发送文本数据时,会出现一类常见的安全问题。此协议指定具有文本数据类型(与二进制或其他类型相反)的消息包含UTF-8编码的数据。尽管仍然指示了长度,并且实现该协议的应用程序应该使用该长度来确定帧的实际结束位置,但以不正确的方式发送数据

encoding may still break assumptions that applications built on top of this protocol may make, leading to anything from misinterpretation of data to loss of data or potential security bugs.

编码仍然可能打破基于此协议构建的应用程序可能做出的假设,从而导致从数据误解到数据丢失或潜在安全漏洞等任何情况。

10.8. Use of SHA-1 by the WebSocket Handshake
10.8. 通过WebSocket握手使用SHA-1

The WebSocket handshake described in this document doesn't depend on any security properties of SHA-1, such as collision resistance or resistance to the second pre-image attack (as described in [RFC4270]).

本文档中描述的WebSocket握手不依赖于SHA-1的任何安全属性,例如抗碰撞或抗第二次图像前攻击(如[RFC4270]中所述)。

11. IANA Considerations
11. IANA考虑
11.1. Registration of New URI Schemes
11.1. 注册新的URI方案
11.1.1. Registration of "ws" Scheme
11.1.1. 登记“ws”计划

A |ws| URI identifies a WebSocket server and resource name.

| ws | URI标识WebSocket服务器和资源名称。

URI scheme name ws

URI方案名称ws

Status Permanent

永久地位

URI scheme syntax Using the ABNF [RFC5234] syntax and ABNF terminals from the URI specification [RFC3986]:

使用ABNF[RFC5234]语法和URI规范[RFC3986]中的ABNF终端的URI方案语法:

           "ws:" "//" authority path-abempty [ "?" query ]
        
           "ws:" "//" authority path-abempty [ "?" query ]
        

The <path-abempty> and <query> [RFC3986] components form the resource name sent to the server to identify the kind of service desired. Other components have the meanings described in [RFC3986].

<path abempty>和<query>[RFC3986]组件构成发送到服务器的资源名称,以标识所需的服务类型。其他组件具有[RFC3986]中所述的含义。

URI scheme semantics The only operation for this scheme is to open a connection using the WebSocket Protocol.

URI方案语义此方案的唯一操作是使用WebSocket协议打开连接。

Encoding considerations Characters in the host component that are excluded by the syntax defined above MUST be converted from Unicode to ASCII as specified in [RFC3987] or its replacement. For the purposes of scheme-based normalization, Internationalized Domain Name (IDN) forms of the host component and their conversions to punycode are considered equivalent (see Section 5.3.3 of [RFC3987]).

编码注意事项主机组件中被上述语法排除的字符必须按照[RFC3987]或其替换中的规定从Unicode转换为ASCII。出于基于方案的规范化目的,主机组件的国际化域名(IDN)形式及其到punycode的转换被认为是等效的(参见[RFC3987]第5.3.3节)。

Characters in other components that are excluded by the syntax defined above MUST be converted from Unicode to ASCII by first encoding the characters as UTF-8 and then replacing the corresponding bytes using their percent-encoded form as defined in the URI [RFC3986] and Internationalized Resource Identifier (IRI) [RFC3987] specifications.

必须先将字符编码为UTF-8,然后使用URI[RFC3986]和国际化资源标识符(IRI)[RFC3987]规范中定义的百分比编码形式替换相应字节,从而将上述语法中排除的其他组件中的字符从Unicode转换为ASCII。

Applications/protocols that use this URI scheme name WebSocket Protocol

使用此URI方案的应用程序/协议名为WebSocket协议

Interoperability considerations Use of WebSocket requires use of HTTP version 1.1 or higher.

互操作性注意事项使用WebSocket需要使用HTTP版本1.1或更高版本。

Security considerations See "Security Considerations" section.

安全注意事项请参阅“安全注意事项”部分。

Contact HYBI WG <hybi@ietf.org>

联系HYBI工作组<hybi@ietf.org>

   Author/Change controller
      IETF <iesg@ietf.org>
        
   Author/Change controller
      IETF <iesg@ietf.org>
        

References RFC 6455

参考RFC6455

11.1.2. Registration of "wss" Scheme
11.1.2. 「水务服务」计划的注册

A |wss| URI identifies a WebSocket server and resource name and indicates that traffic over that connection is to be protected via TLS (including standard benefits of TLS such as data confidentiality and integrity and endpoint authentication).

|wss | URI标识WebSocket服务器和资源名称,并指示通过该连接的流量将通过TLS进行保护(包括TLS的标准好处,如数据机密性、完整性和端点身份验证)。

URI scheme name wss

URI方案名称wss

Status Permanent

永久地位

URI scheme syntax Using the ABNF [RFC5234] syntax and ABNF terminals from the URI specification [RFC3986]:

使用ABNF[RFC5234]语法和URI规范[RFC3986]中的ABNF终端的URI方案语法:

           "wss:" "//" authority path-abempty [ "?" query ]
        
           "wss:" "//" authority path-abempty [ "?" query ]
        

The <path-abempty> and <query> components form the resource name sent to the server to identify the kind of service desired. Other components have the meanings described in [RFC3986].

<path abempty>和<query>组件构成发送到服务器的资源名称,以标识所需的服务类型。其他组件具有[RFC3986]中所述的含义。

URI scheme semantics The only operation for this scheme is to open a connection using the WebSocket Protocol, encrypted using TLS.

URI方案语义此方案的唯一操作是使用WebSocket协议打开连接,使用TLS加密。

Encoding considerations Characters in the host component that are excluded by the syntax defined above MUST be converted from Unicode to ASCII as specified in [RFC3987] or its replacement. For the purposes of scheme-based normalization IDN forms of the host component and their conversions to punycode are considered equivalent (see Section 5.3.3 of [RFC3987]).

编码注意事项主机组件中被上述语法排除的字符必须按照[RFC3987]或其替换中的规定从Unicode转换为ASCII。出于基于方案的规范化目的,主机组件的IDN形式及其到punycode的转换被认为是等效的(见[RFC3987]第5.3.3节)。

Characters in other components that are excluded by the syntax defined above MUST be converted from Unicode to ASCII by first encoding the characters as UTF-8 and then replacing the corresponding bytes using their percent-encoded form as defined in the URI [RFC3986] and IRI [RFC3987] specifications.

必须先将字符编码为UTF-8,然后使用URI[RFC3986]和IRI[RFC3987]规范中定义的百分比编码形式替换相应字节,从而将上述语法排除在外的其他组件中的字符从Unicode转换为ASCII。

Applications/protocols that use this URI scheme name WebSocket Protocol over TLS

使用此URI方案的应用程序/协议名为TLS上的WebSocket协议

Interoperability considerations Use of WebSocket requires use of HTTP version 1.1 or higher.

互操作性注意事项使用WebSocket需要使用HTTP版本1.1或更高版本。

Security considerations See "Security Considerations" section.

安全注意事项请参阅“安全注意事项”部分。

Contact HYBI WG <hybi@ietf.org>

联系HYBI工作组<hybi@ietf.org>

   Author/Change controller
      IETF <iesg@ietf.org>
        
   Author/Change controller
      IETF <iesg@ietf.org>
        

References RFC 6455

参考RFC6455

11.2. Registration of the "WebSocket" HTTP Upgrade Keyword
11.2. 注册“WebSocket”HTTP升级关键字

This section defines a keyword registered in the HTTP Upgrade Tokens Registry as per RFC 2817 [RFC2817].

本节定义了根据RFC 2817[RFC2817]在HTTP升级令牌注册表中注册的关键字。

Name of token WebSocket

令牌WebSocket的名称

   Author/Change controller
      IETF <iesg@ietf.org>
        
   Author/Change controller
      IETF <iesg@ietf.org>
        

Contact HYBI <hybi@ietf.org>

联系海比<hybi@ietf.org>

References RFC 6455

参考RFC6455

11.3. Registration of New HTTP Header Fields
11.3. 注册新的HTTP头字段
11.3.1. Sec-WebSocket-Key
11.3.1. Sec网套键

This section describes a header field registered in the Permanent Message Header Field Names registry [RFC3864].

本节介绍在永久消息标题字段名称注册表[RFC3864]中注册的标题字段。

Header field name Sec-WebSocket-Key

标题字段名称Sec WebSocket键

Applicable protocol http

适用协议http

Status standard

身份标准

Author/Change controller IETF

作者/更改控制器IETF

Specification document(s) RFC 6455

规范文件RFC 6455

Related information This header field is only used for WebSocket opening handshake.

相关信息此标题字段仅用于WebSocket打开握手。

The |Sec-WebSocket-Key| header field is used in the WebSocket opening handshake. It is sent from the client to the server to provide part of the information used by the server to prove that it received a valid WebSocket opening handshake. This helps ensure that the server does not accept connections from non-WebSocket clients (e.g., HTTP clients) that are being abused to send data to unsuspecting WebSocket servers.

| Sec WebSocket Key | header字段用于WebSocket打开握手。它从客户端发送到服务器,以提供服务器用于证明其收到有效WebSocket打开握手的部分信息。这有助于确保服务器不接受来自非WebSocket客户端(例如HTTP客户端)的连接,这些客户端被滥用以将数据发送到不知情的WebSocket服务器。

The |Sec-WebSocket-Key| header field MUST NOT appear more than once in an HTTP request.

| Sec WebSocket Key | header字段在HTTP请求中不得出现多次。

11.3.2. Sec-WebSocket-Extensions
11.3.2. Sec-WebSocket扩展

This section describes a header field for registration in the Permanent Message Header Field Names registry [RFC3864].

本节介绍永久消息标题字段名称注册表[RFC3864]中注册的标题字段。

Header field name Sec-WebSocket-Extensions

标题字段名称Sec WebSocket扩展

Applicable protocol http

适用协议http

Status standard

身份标准

Author/Change controller IETF

作者/更改控制器IETF

Specification document(s) RFC 6455

规范文件RFC 6455

Related information This header field is only used for WebSocket opening handshake.

相关信息此标题字段仅用于WebSocket打开握手。

The |Sec-WebSocket-Extensions| header field is used in the WebSocket opening handshake. It is initially sent from the client to the server, and then subsequently sent from the server to the client, to agree on a set of protocol-level extensions to use for the duration of the connection.

| Sec WebSocket Extensions |标题字段用于WebSocket开始握手。它最初从客户机发送到服务器,然后从服务器发送到客户机,以商定在连接期间使用的一组协议级扩展。

The |Sec-WebSocket-Extensions| header field MAY appear multiple times in an HTTP request (which is logically the same as a single |Sec-WebSocket-Extensions| header field that contains all values. However, the |Sec-WebSocket-Extensions| header field MUST NOT appear more than once in an HTTP response.

| Sec WebSocket Extensions |标头字段可能在HTTP请求中出现多次(逻辑上与包含所有值的单个| Sec WebSocket Extensions |标头字段相同)。但是| Sec WebSocket Extensions |标头字段在HTTP响应中不得出现多次。

11.3.3. Sec-WebSocket-Accept
11.3.3. Sec WebSocket接受

This section describes a header field registered in the Permanent Message Header Field Names registry [RFC3864].

本节介绍在永久消息标题字段名称注册表[RFC3864]中注册的标题字段。

Header field name Sec-WebSocket-Accept

标题字段名称Sec WebSocket Accept

Applicable protocol http

适用协议http

Status standard

身份标准

Author/Change controller IETF

作者/更改控制器IETF

Specification document(s) RFC 6455

规范文件RFC 6455

Related information This header field is only used for the WebSocket opening handshake.

相关信息此标题字段仅用于WebSocket打开握手。

The |Sec-WebSocket-Accept| header field is used in the WebSocket opening handshake. It is sent from the server to the client to confirm that the server is willing to initiate the WebSocket connection.

| Sec WebSocket Accept |标头字段用于WebSocket开始握手。它从服务器发送到客户端,以确认服务器是否愿意启动WebSocket连接。

The |Sec-WebSocket-Accept| header MUST NOT appear more than once in an HTTP response.

| Sec WebSocket Accept |头在HTTP响应中不得出现多次。

11.3.4. Sec-WebSocket-Protocol
11.3.4. Sec-WebSocket协议

This section describes a header field registered in the Permanent Message Header Field Names registry [RFC3864].

本节介绍在永久消息标题字段名称注册表[RFC3864]中注册的标题字段。

Header field name Sec-WebSocket-Protocol

标题字段名Sec WebSocket协议

Applicable protocol http

适用协议http

Status standard

身份标准

Author/Change controller IETF

作者/更改控制器IETF

Specification document(s) RFC 6455

规范文件RFC 6455

Related information This header field is only used for the WebSocket opening handshake.

相关信息此标题字段仅用于WebSocket打开握手。

The |Sec-WebSocket-Protocol| header field is used in the WebSocket opening handshake. It is sent from the client to the server and back from the server to the client to confirm the subprotocol of the connection. This enables scripts to both select a subprotocol and be sure that the server agreed to serve that subprotocol.

| Sec WebSocket Protocol | header字段用于WebSocket打开握手。它从客户端发送到服务器,然后从服务器返回到客户端,以确认连接的子策略。这使脚本既可以选择子策略,又可以确保服务器同意为该子策略提供服务。

The |Sec-WebSocket-Protocol| header field MAY appear multiple times in an HTTP request (which is logically the same as a single |Sec-WebSocket-Protocol| header field that contains all values). However, the |Sec-WebSocket-Protocol| header field MUST NOT appear more than once in an HTTP response.

| Sec WebSocket Protocol | header字段可能在HTTP请求中出现多次(逻辑上与包含所有值的单个| Sec WebSocket Protocol | header字段相同)。但是,| Sec WebSocket Protocol | header字段在HTTP响应中不得出现多次。

11.3.5. Sec-WebSocket-Version
11.3.5. Sec WebSocket版本

This section describes a header field registered in the Permanent Message Header Field Names registry [RFC3864].

本节介绍在永久消息标题字段名称注册表[RFC3864]中注册的标题字段。

Header field name Sec-WebSocket-Version

标题字段名称Sec WebSocket版本

Applicable protocol http

适用协议http

Status standard

身份标准

Author/Change controller IETF

作者/更改控制器IETF

Specification document(s) RFC 6455

规范文件RFC 6455

Related information This header field is only used for the WebSocket opening handshake.

相关信息此标题字段仅用于WebSocket打开握手。

The |Sec-WebSocket-Version| header field is used in the WebSocket opening handshake. It is sent from the client to the server to indicate the protocol version of the connection. This enables servers to correctly interpret the opening handshake and subsequent data being sent from the data, and close the connection if the server cannot interpret that data in a safe manner. The |Sec-WebSocket-Version| header field is also sent from the server to the client on WebSocket handshake error, when the version received from the client does not match a version understood by the server. In such a case, the header field includes the protocol version(s) supported by the server.

| Sec WebSocket Version |标题字段用于WebSocket开始握手。它从客户端发送到服务器,以指示连接的协议版本。这使服务器能够正确解释开始握手和从数据发送的后续数据,并在服务器无法以安全方式解释该数据时关闭连接。当从客户端接收到的版本与服务器可以理解的版本不匹配时,WebSocket握手错误时,| Sec WebSocket Version |标头字段也会从服务器发送到客户端。在这种情况下,标头字段包括服务器支持的协议版本。

Note that there is no expectation that higher version numbers are necessarily backward compatible with lower version numbers.

请注意,并不期望较高版本号必然与较低版本号向后兼容。

The |Sec-WebSocket-Version| header field MAY appear multiple times in an HTTP response (which is logically the same as a single |Sec-WebSocket-Version| header field that contains all values). However, the |Sec-WebSocket-Version| header field MUST NOT appear more than once in an HTTP request.

| Sec WebSocket Version | header字段可能在HTTP响应中出现多次(这在逻辑上与包含所有值的单个| Sec WebSocket Version | header字段相同)。但是,| Sec WebSocket Version | header字段在HTTP请求中不得出现多次。

11.4. WebSocket Extension Name Registry
11.4. WebSocket扩展名注册表

This specification creates a new IANA registry for WebSocket Extension names to be used with the WebSocket Protocol in accordance with the principles set out in RFC 5226 [RFC5226].

本规范根据RFC 5226[RFC5226]中规定的原则,为WebSocket扩展名创建一个新的IANA注册表,用于WebSocket协议。

As part of this registry, IANA maintains the following information:

作为本登记册的一部分,IANA保留以下信息:

Extension Identifier The identifier of the extension, as will be used in the |Sec-WebSocket-Extensions| header field registered in Section 11.3.2 of this specification. The value must conform to the requirements for an extension-token as defined in Section 9.1 of this specification.

扩展标识符扩展的标识符,将在本规范第11.3.2节注册的| Sec WebSocket Extensions |标题字段中使用。该值必须符合本规范第9.1节中定义的扩展令牌要求。

Extension Common Name The name of the extension, as the extension is generally referred to.

扩展公共名称扩展的名称,通常指扩展。

Extension Definition A reference to the document in which the extension being used with the WebSocket Protocol is defined.

扩展定义对文档的引用,其中定义了与WebSocket协议一起使用的扩展。

Known Incompatible Extensions A list of extension identifiers with which this extension is known to be incompatible.

已知不兼容扩展名已知此扩展名与之不兼容的扩展名标识符列表。

WebSocket Extension names are to be subject to the "First Come First Served" IANA registration policy [RFC5226].

WebSocket扩展名应遵守“先到先得”的IANA注册政策[RFC5226]。

There are no initial values in this registry.

此注册表中没有初始值。

11.5. WebSocket Subprotocol Name Registry
11.5. WebSocket子目录名称注册表

This specification creates a new IANA registry for WebSocket Subprotocol names to be used with the WebSocket Protocol in accordance with the principles set out in RFC 5226 [RFC5226].

本规范根据RFC 5226[RFC5226]中规定的原则,为WebSocket子目录名称创建一个新的IANA注册表,用于WebSocket协议。

As part of this registry, IANA maintains the following information:

作为本登记册的一部分,IANA保留以下信息:

Subprotocol Identifier The identifier of the subprotocol, as will be used in the |Sec-WebSocket-Protocol| header field registered in Section 11.3.4 of this specification. The value must conform to the requirements given in item 10 of Section 4.1 of this specification -- namely, the value must be a token as defined by RFC 2616 [RFC2616].

子目录标识符子目录的标识符,将在本规范第11.3.4节中注册的| Sec WebSocket协议|标题字段中使用。该值必须符合本规范第4.1节第10项中给出的要求——即,该值必须是RFC 2616[RFC2616]定义的标记。

Subprotocol Common Name The name of the subprotocol, as the subprotocol is generally referred to.

Subtocol Common Name子程序的名称,通常指子程序。

Subprotocol Definition A reference to the document in which the subprotocol being used with the WebSocket Protocol is defined.

Subtocol定义对文档的引用,其中定义了与WebSocket协议一起使用的Subtocol。

WebSocket Subprotocol names are to be subject to the "First Come First Served" IANA registration policy [RFC5226].

WebSocket子目录名称应遵守“先到先得”IANA注册政策[RFC5226]。

11.6. WebSocket Version Number Registry
11.6. WebSocket版本号注册表

This specification creates a new IANA registry for WebSocket Version Numbers to be used with the WebSocket Protocol in accordance with the principles set out in RFC 5226 [RFC5226].

本规范根据RFC 5226[RFC5226]中规定的原则,为与WebSocket协议一起使用的WebSocket版本号创建一个新的IANA注册表。

As part of this registry, IANA maintains the following information:

作为本登记册的一部分,IANA保留以下信息:

Version Number The version number to be used in the |Sec-WebSocket-Version| is specified in Section 4.1 of this specification. The value must be a non-negative integer in the range between 0 and 255 (inclusive).

版本号本规范第4.1节规定了“Sec WebSocket版本”中使用的版本号。该值必须是介于0和255(包括0和255)之间的非负整数。

Reference The RFC requesting a new version number or a draft name with version number (see below).

参考RFC请求新版本号或具有版本号的草案名称(见下文)。

Status Either "Interim" or "Standard". See below for description.

状态为“临时”或“标准”。请参见下面的描述。

A version number is designated as either "Interim" or "Standard".

版本号指定为“临时”或“标准”。

A "Standard" version number is documented in an RFC and used to identify a major, stable version of the WebSocket protocol, such as the version defined by this RFC. "Standard" version numbers are subject to the "IETF Review" IANA registration policy [RFC5226].

“标准”版本号记录在RFC中,用于标识WebSocket协议的主要、稳定版本,如本RFC定义的版本。“标准”版本号受“IETF审查”IANA注册政策[RFC5226]的约束。

An "Interim" version number is documented in an Internet-Draft and used to help implementors identify and interoperate with deployed versions of the WebSocket protocol, such as versions developed before the publication of this RFC. "Interim" version numbers are subject to the "Expert Review" IANA registration policy [RFC5226], with the chairs of the HYBI Working Group (or, if the working group closes, the Area Directors for the IETF Applications Area) being the initial Designated Experts.

“临时”版本号记录在互联网草案中,用于帮助实施者识别WebSocket协议的已部署版本并与之进行互操作,例如在发布本RFC之前开发的版本。“临时”版本号受“专家评审”IANA注册政策[RFC5226]的约束,HYBI工作组主席(或者,如果工作组结束,IETF应用领域的区域主管)是最初指定的专家。

IANA has added initial values to the registry as follows.

IANA已将初始值添加到注册表中,如下所示。

   +--------+-----------------------------------------+----------+
   |Version |                Reference                |  Status  |
   | Number |                                         |          |
   +--------+-----------------------------------------+----------+
   | 0      + draft-ietf-hybi-thewebsocketprotocol-00 | Interim  |
   +--------+-----------------------------------------+----------+
   | 1      + draft-ietf-hybi-thewebsocketprotocol-01 | Interim  |
   +--------+-----------------------------------------+----------+
   | 2      + draft-ietf-hybi-thewebsocketprotocol-02 | Interim  |
   +--------+-----------------------------------------+----------+
   | 3      + draft-ietf-hybi-thewebsocketprotocol-03 | Interim  |
   +--------+-----------------------------------------+----------+
   | 4      + draft-ietf-hybi-thewebsocketprotocol-04 | Interim  |
   +--------+-----------------------------------------+----------+
   | 5      + draft-ietf-hybi-thewebsocketprotocol-05 | Interim  |
   +--------+-----------------------------------------+----------+
   | 6      + draft-ietf-hybi-thewebsocketprotocol-06 | Interim  |
   +--------+-----------------------------------------+----------+
   | 7      + draft-ietf-hybi-thewebsocketprotocol-07 | Interim  |
   +--------+-----------------------------------------+----------+
   | 8      + draft-ietf-hybi-thewebsocketprotocol-08 | Interim  |
   +--------+-----------------------------------------+----------+
   | 9      +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 10     +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 11     +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 12     +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 13     +                RFC 6455                 | Standard |
   +--------+-----------------------------------------+----------+
        
   +--------+-----------------------------------------+----------+
   |Version |                Reference                |  Status  |
   | Number |                                         |          |
   +--------+-----------------------------------------+----------+
   | 0      + draft-ietf-hybi-thewebsocketprotocol-00 | Interim  |
   +--------+-----------------------------------------+----------+
   | 1      + draft-ietf-hybi-thewebsocketprotocol-01 | Interim  |
   +--------+-----------------------------------------+----------+
   | 2      + draft-ietf-hybi-thewebsocketprotocol-02 | Interim  |
   +--------+-----------------------------------------+----------+
   | 3      + draft-ietf-hybi-thewebsocketprotocol-03 | Interim  |
   +--------+-----------------------------------------+----------+
   | 4      + draft-ietf-hybi-thewebsocketprotocol-04 | Interim  |
   +--------+-----------------------------------------+----------+
   | 5      + draft-ietf-hybi-thewebsocketprotocol-05 | Interim  |
   +--------+-----------------------------------------+----------+
   | 6      + draft-ietf-hybi-thewebsocketprotocol-06 | Interim  |
   +--------+-----------------------------------------+----------+
   | 7      + draft-ietf-hybi-thewebsocketprotocol-07 | Interim  |
   +--------+-----------------------------------------+----------+
   | 8      + draft-ietf-hybi-thewebsocketprotocol-08 | Interim  |
   +--------+-----------------------------------------+----------+
   | 9      +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 10     +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 11     +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 12     +                Reserved                 |          |
   +--------+-----------------------------------------+----------+
   | 13     +                RFC 6455                 | Standard |
   +--------+-----------------------------------------+----------+
        
11.7. WebSocket Close Code Number Registry
11.7. WebSocket关闭代码注册表

This specification creates a new IANA registry for WebSocket Connection Close Code Numbers in accordance with the principles set out in RFC 5226 [RFC5226].

本规范根据RFC 5226[RFC5226]中规定的原则,为WebSocket连接关闭代码创建新的IANA注册表。

As part of this registry, IANA maintains the following information:

作为本登记册的一部分,IANA保留以下信息:

Status Code The Status Code denotes a reason for a WebSocket connection closure as per Section 7.4 of this document. The status code is an integer number between 1000 and 4999 (inclusive).

状态代码根据本文件第7.4节,状态代码表示WebSocket连接关闭的原因。状态代码是介于1000和4999(含)之间的整数。

Meaning The meaning of the status code. Each status code has to have a unique meaning.

表示状态代码的含义。每个状态代码必须具有唯一的含义。

Contact A contact for the entity reserving the status code.

联系保留状态代码的实体的联系人。

Reference The stable document requesting the status codes and defining their meaning. This is required for status codes in the range 1000-2999 and recommended for status codes in the range 3000-3999.

参考要求状态代码并定义其含义的稳定文件。这对于1000-2999范围内的状态代码是必需的,对于3000-3999范围内的状态代码是推荐的。

WebSocket Close Code Numbers are subject to different registration requirements depending on their range. Requests for status codes for use by this protocol and its subsequent versions or extensions are subject to any one of the "Standards Action", "Specification Required" (which implies "Designated Expert"), or "IESG Review" IANA registration policies and should be granted in the range 1000-2999. Requests for status codes for use by libraries, frameworks, and applications are subject to the "First Come First Served" IANA registration policy and should be granted in the range 3000-3999. The range of status codes from 4000-4999 is designated for Private Use. Requests should indicate whether they are requesting status codes for use by the WebSocket Protocol (or a future version of the protocol), by extensions, or by libraries/frameworks/applications.

WebSocket关闭代码根据其范围的不同,有不同的注册要求。本协议及其后续版本或扩展使用的状态代码请求受“标准行动”、“所需规范”(意指“指定专家”)或“IESG审查”IANA注册政策的任何一项约束,并应在1000-2999范围内予以批准。图书馆、框架和应用程序使用状态代码的请求受“先到先得”IANA注册政策的约束,应在3000-3999范围内予以批准。4000-4999之间的状态代码范围指定为私人使用。请求应指明它们是请求WebSocket协议(或协议的未来版本)、扩展还是库/框架/应用程序使用的状态代码。

IANA has added initial values to the registry as follows.

IANA已将初始值添加到注册表中,如下所示。

     |Status Code | Meaning         | Contact       | Reference |
    -+------------+-----------------+---------------+-----------|
     | 1000       | Normal Closure  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1001       | Going Away      | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1002       | Protocol error  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1003       | Unsupported Data| hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1004       | ---Reserved---- | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1005       | No Status Rcvd  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1006       | Abnormal Closure| hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1007       | Invalid frame   | hybi@ietf.org | RFC 6455  |
     |            | payload data    |               |           |
    -+------------+-----------------+---------------+-----------|
     | 1008       | Policy Violation| hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1009       | Message Too Big | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1010       | Mandatory Ext.  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1011       | Internal Server | hybi@ietf.org | RFC 6455  |
     |            | Error           |               |           |
    -+------------+-----------------+---------------+-----------|
     | 1015       | TLS handshake   | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
        
     |Status Code | Meaning         | Contact       | Reference |
    -+------------+-----------------+---------------+-----------|
     | 1000       | Normal Closure  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1001       | Going Away      | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1002       | Protocol error  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1003       | Unsupported Data| hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1004       | ---Reserved---- | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1005       | No Status Rcvd  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1006       | Abnormal Closure| hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1007       | Invalid frame   | hybi@ietf.org | RFC 6455  |
     |            | payload data    |               |           |
    -+------------+-----------------+---------------+-----------|
     | 1008       | Policy Violation| hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1009       | Message Too Big | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1010       | Mandatory Ext.  | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
     | 1011       | Internal Server | hybi@ietf.org | RFC 6455  |
     |            | Error           |               |           |
    -+------------+-----------------+---------------+-----------|
     | 1015       | TLS handshake   | hybi@ietf.org | RFC 6455  |
    -+------------+-----------------+---------------+-----------|
        
11.8. WebSocket Opcode Registry
11.8. WebSocket操作码注册表

This specification creates a new IANA registry for WebSocket Opcodes in accordance with the principles set out in RFC 5226 [RFC5226].

本规范根据RFC 5226[RFC5226]中规定的原则,为WebSocket操作码创建新的IANA注册表。

As part of this registry, IANA maintains the following information:

作为本登记册的一部分,IANA保留以下信息:

Opcode The opcode denotes the frame type of the WebSocket frame, as defined in Section 5.2. The opcode is an integer number between 0 and 15, inclusive.

操作码操作码表示第5.2节中定义的WebSocket框架的框架类型。操作码是一个介于0和15之间(含0和15)的整数。

Meaning The meaning of the opcode value.

表示操作码值的含义。

Reference The specification requesting the opcode.

请参考请求操作码的规范。

WebSocket Opcode numbers are subject to the "Standards Action" IANA registration policy [RFC5226].

WebSocket操作码编号受“标准行动”IANA注册政策[RFC5226]的约束。

IANA has added initial values to the registry as follows.

IANA已将初始值添加到注册表中,如下所示。

     |Opcode  | Meaning                             | Reference |
    -+--------+-------------------------------------+-----------|
     | 0      | Continuation Frame                  | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 1      | Text Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 2      | Binary Frame                        | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 8      | Connection Close Frame              | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 9      | Ping Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 10     | Pong Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
        
     |Opcode  | Meaning                             | Reference |
    -+--------+-------------------------------------+-----------|
     | 0      | Continuation Frame                  | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 1      | Text Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 2      | Binary Frame                        | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 8      | Connection Close Frame              | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 9      | Ping Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
     | 10     | Pong Frame                          | RFC 6455  |
    -+--------+-------------------------------------+-----------|
        
11.9. WebSocket Framing Header Bits Registry
11.9. WebSocket帧头位注册表

This specification creates a new IANA registry for WebSocket Framing Header Bits in accordance with the principles set out in RFC 5226 [RFC5226]. This registry controls assignment of the bits marked RSV1, RSV2, and RSV3 in Section 5.2.

本规范根据RFC 5226[RFC5226]中规定的原则,为WebSocket帧头位创建新的IANA注册表。该注册表控制第5.2节中标记为RSV1、RSV2和RSV3的位的分配。

These bits are reserved for future versions or extensions of this specification.

这些位保留用于本规范的未来版本或扩展。

WebSocket Framing Header Bits assignments are subject to the "Standards Action" IANA registration policy [RFC5226].

WebSocket帧头比特分配受“标准行动”IANA注册政策[RFC5226]的约束。

12. Using the WebSocket Protocol from Other Specifications
12. 使用其他规范中的WebSocket协议

The WebSocket Protocol is intended to be used by another specification to provide a generic mechanism for dynamic author-defined content, e.g., in a specification defining a scripted API.

WebSocket协议旨在由另一个规范使用,为动态作者定义的内容提供通用机制,例如,在定义脚本API的规范中。

Such a specification first needs to _Establish a WebSocket Connection_, providing that algorithm with:

此类规范首先需要建立WebSocket连接,前提是该算法具有:

o The destination, consisting of a /host/ and a /port/.

o 目标,由/host/和/port/组成。

o A /resource name/, which allows for multiple services to be identified at one host and port.

o A/resource name/,允许在一个主机和端口上标识多个服务。

o A /secure/ flag, which is true if the connection is to be encrypted and false otherwise.

o A/secure/flag,如果要加密连接,则为true;否则为false。

o An ASCII serialization of an origin [RFC6454] that is being made responsible for the connection.

o 负责连接的源[RFC6454]的ASCII序列化。

o Optionally, a string identifying a protocol that is to be layered over the WebSocket connection.

o (可选)标识要在WebSocket连接上分层的协议的字符串。

The /host/, /port/, /resource name/, and /secure/ flag are usually obtained from a URI using the steps to parse a WebSocket URI's components. These steps fail if the URI does not specify a WebSocket.

/host/、/port/、/resource name/、和/secure/标志通常通过解析WebSocket URI组件的步骤从URI中获取。如果URI未指定WebSocket,则这些步骤将失败。

If at any time the connection is to be closed, then the specification needs to use the _Close the WebSocket Connection_ algorithm (Section 7.1.1).

如果在任何时候都要关闭连接,则规范需要使用“关闭WebSocket连接”算法(第7.1.1节)。

Section 7.1.4 defines when _The WebSocket Connection is Closed_.

第7.1.4节定义了何时关闭WebSocket连接。

While a connection is open, the specification will need to handle the cases when _A WebSocket Message Has Been Received_ (Section 6.2).

当连接打开时,规范将需要处理收到WebSocket消息的情况(第6.2节)。

To send some data /data/ to an open connection, the specification needs to _Send a WebSocket Message_ (Section 6.1).

要向打开的连接发送一些数据,规范需要发送WebSocket消息(第6.1节)。

13. Acknowledgements
13. 致谢

Special thanks are due to Ian Hickson, who was the original author and editor of this protocol. The initial design of this specification benefitted from the participation of many people in the WHATWG and WHATWG mailing list. Contributions to that specification are not tracked by section, but a list of all who contributed to that specification is given in the WHATWG HTML specification at http://whatwg.org/html5.

特别感谢Ian Hickson,他是本协议的原始作者和编辑。本规范的初始设计得益于WHATWG和WHATWG邮件列表中许多人的参与。对该规范的贡献不按章节进行跟踪,但WHATWG HTML规范中给出了对该规范做出贡献的所有人的列表http://whatwg.org/html5.

Special thanks also to John Tamplin for providing a significant amount of text for the "Data Framing" section of this specification.

还特别感谢John Tamplin为本规范的“数据框架”部分提供了大量文本。

Special thanks also to Adam Barth for providing a significant amount of text and background research for the "Data Masking" section of this specification.

特别感谢Adam Barth为本规范的“数据屏蔽”部分提供了大量的文本和背景研究。

Special thanks to Lisa Dusseault for the Apps Area review (and for helping to start this work), Richard Barnes for the Gen-Art review, and Magnus Westerlund for the Transport Area Review. Special thanks to HYBI WG past and present WG chairs who tirelessly worked behind the scene to move this work toward completion: Joe Hildebrand, Salvatore Loreto, and Gabriel Montenegro. And last but not least, special thank you to the responsible Area Director Peter Saint-Andre.

特别感谢Lisa Dusseault的应用领域评论(以及帮助开始这项工作),Richard Barnes的Gen Art评论,以及Magnus Westerlund的交通领域评论。特别感谢HYBI工作组过去和现在的工作组主席,他们不知疲倦地在幕后工作,将这项工作推向完成:乔·希尔德布兰德、萨尔瓦托雷·洛雷托和加布里埃尔·黑山。最后但并非最不重要的一点是,特别感谢责任区主任彼得·圣安德烈。

Thank you to the following people who participated in discussions on the HYBI WG mailing list and contributed ideas and/or provided detailed reviews (the list is likely to be incomplete): Greg Wilkins, John Tamplin, Willy Tarreau, Maciej Stachowiak, Jamie Lokier, Scott Ferguson, Bjoern Hoehrmann, Julian Reschke, Dave Cridland, Andy Green, Eric Rescorla, Inaki Baz Castillo, Martin Thomson, Roberto Peon, Patrick McManus, Zhong Yu, Bruce Atherton, Takeshi Yoshino, Martin J. Duerst, James Graham, Simon Pieters, Roy T. Fielding, Mykyta Yevstifeyev, Len Holgate, Paul Colomiets, Piotr Kulaga, Brian Raymor, Jan Koehler, Joonas Lehtolahti, Sylvain Hellegouarch, Stephen Farrell, Sean Turner, Pete Resnick, Peter Thorson, Joe Mason, John Fallows, and Alexander Philippou. Note that people listed above didn't necessarily endorse the end result of this work.

感谢以下参与HYBI工作组邮件列表讨论并提供想法和/或详细评论(列表可能不完整)的人员:格雷格·威尔金斯、约翰·坦普林、威利·塔罗、麦基·斯塔乔亚克、杰米·洛基、斯科特·弗格森、比约恩·霍尔曼、朱利安·雷什克、戴夫·克里德兰、安迪·格林、,Eric Rescorla,Inaki Baz Castillo,Martin Thomson,Roberto Paon,Patrick McManus,钟宇,Bruce Atherton,Takeshi Yoshino,Martin J.Duerst,James Graham,Simon Pieters,Roy T.Fielding,Mykyta Yevstifeyev,Len Holgate,Paul Colomites,Piotr Kulaga,Brian Raymor,Jan Koehler,Joonas Lehtolahti,Sylvain Hellegouch,Stephen Farrell,Sean Turner,彼得·雷斯尼克、彼得·索森、乔·梅森、约翰·法洛斯和亚历山大·菲利普。请注意,上面列出的人并不一定赞同这项工作的最终结果。

14. References
14. 工具书类
14.1. Normative References
14.1. 规范性引用文件

[ANSI.X3-4.1986] American National Standards Institute, "Coded Character Set - 7-bit American Standard Code for Information Interchange", ANSI X3.4, 1986.

[ANSI.X3-4.1986]美国国家标准协会,“编码字符集-信息交换用7位美国标准代码”,ANSI X3.41986。

[FIPS.180-3] National Institute of Standards and Technology, "Secure Hash Standard", FIPS PUB 180-3, October 2008, <http://csrc.nist.gov/publications/fips/fips180-3/ fips180-3_final.pdf>.

[FIPS.180-3]国家标准与技术研究所,“安全哈希标准”,FIPS PUB 180-3,2008年10月<http://csrc.nist.gov/publications/fips/fips180-3/ fips180-3_final.pdf>。

[RFC1928] Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D., and L. Jones, "SOCKS Protocol Version 5", RFC 1928, March 1996.

[RFC1928]Leech,M.,Ganis,M.,Lee,Y.,Kuris,R.,Koblas,D.,和L.Jones,“SOCKS协议版本5”,RFC 19281996年3月。

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2119]Bradner,S.,“RFC中用于表示需求水平的关键词”,BCP 14,RFC 2119,1997年3月。

[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.

[RFC2616]菲尔丁,R.,盖蒂斯,J.,莫卧儿,J.,弗莱斯蒂克,H.,马斯特,L.,利奇,P.,和T.伯纳斯李,“超文本传输协议——HTTP/1.1”,RFC 2616,1999年6月。

[RFC2817] Khare, R. and S. Lawrence, "Upgrading to TLS Within HTTP/1.1", RFC 2817, May 2000.

[RFC2817]Khare,R.和S.Lawrence,“在HTTP/1.1中升级到TLS”,RFC 28172000年5月。

[RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.

[RFC2818]Rescorla,E.,“TLS上的HTTP”,RFC2818,2000年5月。

[RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.

[RFC3629]Yergeau,F.,“UTF-8,ISO 10646的转换格式”,STD 63,RFC 3629,2003年11月。

[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004.

[RFC3864]Klyne,G.,Nottingham,M.和J.Mogul,“消息头字段的注册程序”,BCP 90,RFC 3864,2004年9月。

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.

[RFC3986]Berners Lee,T.,Fielding,R.,和L.Masinter,“统一资源标识符(URI):通用语法”,STD 66,RFC 3986,2005年1月。

[RFC3987] Duerst, M. and M. Suignard, "Internationalized Resource Identifiers (IRIs)", RFC 3987, January 2005.

[RFC3987]Duerst,M.和M.Suignard,“国际化资源标识符(IRIs)”,RFC 3987,2005年1月。

[RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.

[RFC4086]Eastlake,D.,Schiller,J.,和S.Crocker,“安全的随机性要求”,BCP 106,RFC 4086,2005年6月。

[RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, October 2006.

[RFC4648]Josefsson,S.,“Base16、Base32和Base64数据编码”,RFC4648,2006年10月。

[RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, May 2008.

[RFC5226]Narten,T.和H.Alvestrand,“在RFCs中编写IANA注意事项部分的指南”,BCP 26,RFC 5226,2008年5月。

[RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, January 2008.

[RFC5234]Crocker,D.和P.Overell,“语法规范的扩充BNF:ABNF”,STD 68,RFC 5234,2008年1月。

[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.

[RFC5246]Dierks,T.和E.Rescorla,“传输层安全(TLS)协议版本1.2”,RFC 5246,2008年8月。

[RFC6066] Eastlake, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, January 2011.

[RFC6066]Eastlake,D.,“传输层安全(TLS)扩展:扩展定义”,RFC6066,2011年1月。

[RFC6454] Barth, A., "The Web Origin Concept", RFC 6454, December 2011.

[RFC6454]Barth,A.,“网络起源概念”,RFC 64542011年12月。

14.2. Informative References
14.2. 资料性引用

[RFC4122] Leach, P., Mealling, M., and R. Salz, "A Universally Unique IDentifier (UUID) URN Namespace", RFC 4122, July 2005.

[RFC4122]Leach,P.,Mealling,M.和R.Salz,“通用唯一标识符(UUID)URN名称空间”,RFC 4122,2005年7月。

[RFC4270] Hoffman, P. and B. Schneier, "Attacks on Cryptographic Hashes in Internet Protocols", RFC 4270, November 2005.

[RFC4270]Hoffman,P.和B.Schneier,“对互联网协议中加密哈希的攻击”,RFC 42702005年11月。

[RFC5321] Klensin, J., "Simple Mail Transfer Protocol", RFC 5321, October 2008.

[RFC5321]Klensin,J.,“简单邮件传输协议”,RFC 53212008年10月。

[RFC6202] Loreto, S., Saint-Andre, P., Salsano, S., and G. Wilkins, "Known Issues and Best Practices for the Use of Long Polling and Streaming in Bidirectional HTTP", RFC 6202, April 2011.

[RFC6202]Loreto,S.,Saint Andre,P.,Salsano,S.,和G.Wilkins,“双向HTTP中使用长轮询和流的已知问题和最佳实践”,RFC 62022,2011年4月。

[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265, April 2011.

[RFC6265]Barth,A.,“HTTP状态管理机制”,RFC6265,2011年4月。

[TALKING] Huang, L-S., Chen, E., Barth, A., Rescorla, E., and C. Jackson, "Talking to Yourself for Fun and Profit", 2010, <http://w2spconf.com/2011/papers/websocket.pdf>.

[谈话]黄,L-S.,陈,E.,巴特,A.,雷斯科拉,E.,和C.杰克逊,“为了乐趣和利益而与自己交谈”,2010年<http://w2spconf.com/2011/papers/websocket.pdf>.

[W3C.REC-wsc-ui-20100812] Roessler, T. and A. Saldhana, "Web Security Context: User Interface Guidelines", World Wide Web Consortium Recommendation REC-wsc-ui-20100812, August 2010, <http://www.w3.org/TR/2010/REC-wsc-ui-20100812/>.

[W3C.REC-wsc-ui-20100812]Roessler,T.和A.Saldhana,“网络安全环境:用户界面指南”,万维网联盟建议REC-wsc-ui-20100812,2010年8月<http://www.w3.org/TR/2010/REC-wsc-ui-20100812/>.

Latest version available at <http://www.w3.org/TR/wsc-ui/>.

最新版本可于<http://www.w3.org/TR/wsc-ui/>.

[WSAPI] Hickson, I., "The WebSocket API", W3C Working Draft WD-websockets-20110929, September 2011, <http://www.w3.org/TR/2011/WD-websockets-20110929/>.

[WSAPI]Hickson,I.,“WebSocket API”,W3C工作草案WD-WebSocket-201109292011年9月<http://www.w3.org/TR/2011/WD-websockets-20110929/>.

Latest version available at <http://www.w3.org/TR/websockets/>.

最新版本可于<http://www.w3.org/TR/websockets/>.

[XMLHttpRequest] van Kesteren, A., Ed., "XMLHttpRequest", W3C Candidate Recommendation CR-XMLHttpRequest-20100803, August 2010, <http://www.w3.org/TR/2010/CR-XMLHttpRequest-20100803/>.

[XMLHttpRequest]van Kesteren,A.,编辑,“XMLHttpRequest”,W3C候选建议CR-XMLHttpRequest-20100803,2010年8月<http://www.w3.org/TR/2010/CR-XMLHttpRequest-20100803/>.

Latest version available at <http://www.w3.org/TR/XMLHttpRequest/>.

最新版本可于<http://www.w3.org/TR/XMLHttpRequest/>.

Authors' Addresses

作者地址

Ian Fette Google, Inc.

伊恩·费特谷歌公司。

   EMail: ifette+ietf@google.com
   URI:   http://www.ianfette.com/
        
   EMail: ifette+ietf@google.com
   URI:   http://www.ianfette.com/
        

Alexey Melnikov Isode Ltd. 5 Castle Business Village 36 Station Road Hampton, Middlesex TW12 2BX UK

Alexey Melnikov Isode Ltd.英国米德尔塞克斯郡汉普顿车站路36号城堡商业村5号TW12 2BX

   EMail: Alexey.Melnikov@isode.com
        
   EMail: Alexey.Melnikov@isode.com