【译】WebSocket协议第一章——介绍(Introduction)

概述

本文为WebSocket协议的第一章,本文翻译的主要内容为针对整个WebSocket进行一个简单而又全面的介绍。经过这篇文章咱们可以对WebSocket有一个总体的大体了解。html

1 介绍

本章为协议正文内容的第一章(Introduction)。web

1.1 背景

此章节为非规范章节。后端

在历史上,建立一个客户端和服务端的双向数据Web应用(例如IM应用和游戏应用)须要向服务端频繁发送不一样于通常HTTP请求的HTTP轮询请求来从服务端上游更新数据。浏览器

这个方法有许多的问题:安全

  • 服务端被迫使用大量的的潜在的TCP链接与客户端进行交互:一部分是用来发送数据,而另外一部分是用来接收数据。
  • 应用层无线传输协议(HTTP)开销较大,每个客户端到服务端的消息都有一个HTTP头。
  • 客户端脚本必须包含一个发送和接收对应的映射表来进行对应数据处理。

一个简单的解决方案是使用一个简单的TCP连接来进行双向数据传输。这就是WebSocket提供的能力。结合WebSocket的API,它可以提供一个能够替代HTTP轮询的方法来知足Web页面和远端服务器的双向数据通讯。服务器

相同的技术能够被用到许多的Web应用:游戏、股票应用、多人协做应用、与后端服务实时交互的用户接口等。websocket

WebSocket协议设计的缘由是取代已经存在的使用HTTP做为传输层的双向通讯技术,从而使得已经存在的基础服务(如代理、过滤器、认证服务)可以受益。这种技术是基于效率和可靠性权衡后来进行实现的,而HTTP协议最初也不是用来作双向数据通讯的。WebSocket协议尝试实现基于现有的HTTP基础服务来实如今现有环境中双向通讯技术的目标;因此,即便这意味着在现有环境中会有一些复杂性,它在设计中仍然使用了HTTP的80和443端口,以及支持支持HTTP代理。然而,这个设计并无限制WebSocket只能使用HTTP端口,在之后的实现中也可使用一个简单的握手方式来使用特定的端口而不须要改动整个协议。最后一点很重要,由于双向消息的通讯方式不是很符合标准HTTP的模式,可能致使在某些组件中出现异常的负载。cookie

1.2 协议概览

此节为非规范章节。网络

这个协议有两部分:握手和数据传输。负载均衡

来自客户端的握手数据以下所示:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

服务端的握手响应以下所示:

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

客户端请求的第一行(leading line)遵循了HTTP请求行的格式。

服务端的第一行(leading line)遵循了HTTP状态行的格式。

HTTP请求行和状态行的规范定义在RFC2616

在两个协议中,第一行header下面是一组无序的header字段。这些header字段包含的内容在本文的第四节。另外的header字段如cookies,也有可能存在。格式和解析头信息被定义在了RFC2616

当客户端和服务端都发送了他们的握手协议,而且当握手已经成功,那么数据传输就开始了。这是一个双方均可以独立发送任意数据的双向通讯渠道。

在握手成功之后,客户端和服务端传输的数据来回传输的数据单位,咱们在规范中称为消息(messages)。在传输中,一条消息有一个或者多个帧组成。WebSocket中的消息不须要对应特定网络层中的帧,一条零散的消息可能由中间人合并或者拆分红网络层的帧。

帧有关联的类型。同一条消息的每一帧都包含相同类型的数据。一般来讲,它能够是文本数据(UTF-8编码)、二进制数据(留给应用解析的数据)和控制帧数据(不是用来传输数据,而是用来做为协议层的特定符号,如关闭链接帧)。当前版本的协议定义了6中控制帧类型而且预留了10个保留类型。

1.3 链接握手

此节为非规范章节。

在链接握手为了与基于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

遵守RFC2616,客户端在握手过程当中发送的header字段多是乱序的,因此收到的header字段的顺序不一样也没有太大影响。

GET方法的请求URI(Request-URI)是用于定义WebSocket链接的终端,容许同一个IP对多个域名提供服务,也容许多个WebSocket终端链接同一个服务器。

客户端在每个握手的Hostheader里面包含了一个主机域名。因此客户端和服务端均可以校验哪些域名在使用中。

另外的header字段是用来肯定WebSocket协议的选项。这个版本中提供的特定选项是子协议选择(Sec-WebSocket-Protocol)、客户端支持的扩展列表(Sec-WebSocket-Extensions)、Originheader字段等。请求header字段Sec-WebSocket-Protocol能够用来标识哪些子协议(基于WebSocket的应用高层协议)是客户端能够支持的。服务端回从中选择零或者一个支持的协议而且在响应握手中输出它选择的那个协议。

Sec-WebSocket-Protocol: chat

服务端也能够设置cookie相关字段来设置cookie相关属性,具体文档见RFC6265

1.4 结束握手

此节为非规范章节。

结束握手远比链接握手简单。

任何一端均可以发送一个包含特定关闭握手的控制帧数据(详情见5.5.1节)。收到此帧后,另外一端在不发送任何数据后会发送一个结束帧做为响应。收到另外一端的结束帧后,最开始发送控制帧的端在没有数据须要发送时,就会安全的关闭此链接。

在发送了一个代表链接须要被关闭的控制帧后,这个客户端不会再发送任何的数据;在收到一个代表链接须要被关闭的控制帧后,这个客户端会丢弃此后的全部数据。

这样比两边同时发起握手要更加安全。

这个结束握手的目标是来补充TCP结束握手中的一些内容(FIN/ACK),而这是由于TCP结束握手在端与端之间并不必定可靠,尤为是有代理和其余的网络中介时会变得不可靠。

在发送关闭帧等待接受另外一端的响应关闭帧时,在某些状况下能够避免数据的没必要要丢失。例如,在某些平台中,若是一个socket在接收队列有数据时被关闭,会发送一个RST包,尽管数据还在等待被读取,这也会致使接收到RST的一方数据接收失败。

1.5 设计哲学

此节为非规范章节。

WebSocket协议设计的原理就是设计为最的小框架(惟一的约束就是使这个协议是基于帧而不是流,而且能够支持Unicode文本和二进制帧二者中的任意一种)。在基于WebSocket的应用层中,元数据是应该分层的,就像基于TCP的应用层(例如HTTP)同样。

从概念上来看,WebSocket层是基于TCP实现的,增长了如下的内容:

  • 增长了一个基于浏览器的同源策略模型
  • 增长了一个地址和协议命名机制来在同一个端口上支持多个服务,在同一个IP地址自持多个主机名
  • 在TCP协议上分层构建框架机制回到TCP使用的IP包机制,可是没有长度限制
  • 包含一个设计用于处理有代理和其余网络中介的状况的额外的结束握手协议

除此以外,WebSocket没有增长任何东西。基本上WebSocket的的目标是在约束的条件下像脚本提供尽量接近原生的TCP的Web服务。它同时考虑了服务器在进行握手和处理有效的HTTP升级请求时,能够和HTTP共用一个服务。你们也可使用其余协议来创建从客户端到服务端的消息通讯,但WebSocket的协议的目的是为了提供一个相对简单的能够和HTTP共存,而且依赖于HTTP基础设施(如代理)的协议。这个很是接近TCP的协议由于基于安全的基础设施和针对性的可以简单使用和让事情变得更简单的补充(例如消息语义的补充),所以能够安全使用。

这个协议具备可扩展性,将来的版本可能会引入一些新的概念如多路复用。

1.6 安全模型

此节为非规范章节。

当WebSocket协议在web网页中应用时,WebSocket协议在Web页面与WebSocket服务器创建链接时使用基于web浏览器的同源策略模型。因此说,当WebSocket协议在一个特定的客户端(不是web浏览器里面的网页)直接使用时,同源策略模型就不生效了,客户端能够接受任意的源数据。

该协议没法与已经存在的如SMTP(RFC5421)和HTTP协议的服务器创建链接,若是须要的话,HTTP服务器能够选择支持该协议。该协议还实现了严格约束的握手过程和限制数据不能在握手完成和创建链接以前插入数据进行传输(所以限制了许多被影响的服务器)。

WebSocket服务器一样没法与其余协议尤为是HTTP创建链接。例如,一个HTML“表单”可能会提交给一个WebSocket服务器。WebSocket服务端只能读取包含特定的由WebSocket客户端发送的字段的握手数据。尤为是在编写这个规范时,攻击者不能只使用HTML和JavaScript APIs的Web浏览器来发送以Sec-开头的字段。

1.7 与TCP和HTTP的关系

此节为非规范章节。

WebSocket协议是独立的基于TCP的协议。他和HTTP的惟一关系是创建链接的握手操做的升级请求是基于HTTP服务器的。

WebSocket默认使用80端口进行链接,而基于TLS(RFC2818)的WebSocket链接是基于443端口的。

1.8 创建链接

此节为非规范章节。

当创建了一个和HTTP服务器共享端口的链接时(这种状况颇有可能发送在与80和443端口通讯上),这个连接将会给HTTP服务器发送一个常规的GET请求来进行升级。在一个IP地址和一个单一的服务器来应对单一主机名的通讯这种相对简单的设置上,基于WebSocket协议的系统能够经过一个更加实用的方法来进行部署。在更详细的设置(例如负载均衡和多服务器),与HTTP服务器分开的专属的WebSocket链接集群可能更加易于管理。在编写这个规范时,咱们应该知道在80端口和443端口创建WebSocket链接的成功率是不一样的,在443端口上面创建的链接很明显更容易成功,尽管这可能随着时间的变化而改变。

1.9 使用WebSocket协议的子协议

客户端能够经过在握手阶段中的Sec-WebSocket-protocol字段来请求服务端使用指定的子协议。若是指定了这个字段,服务器须要包含相同的字段,而且从子协议的之中选择一个值做为创建链接的响应。

子协议的名称能够按照第11.5节的方法进行注册。为了不潜在的冲突,推荐使用包含ASCII码的域名名称做为子协议名。例如,Example Corporation创造了在Web上经过多个服务器实现的一个聊天子协议(Chat subprotocol),他们能够叫作chat.example.com。若是Example Organization创造了他们相对的子协议叫作chat.example.org,这两个子协议能够被服务器同时实现,服务器能够根据客户端来动态的选择使用哪个子协议。

子协议也能够经过修更名字的方式来向后兼容,例如:将bookings.example.net改成v2.bookings.example.net。WebSocket客户端可以彻底的区分这些子协议。向后兼容的版本控制能够经过复用相同的子协议字符和当心设计的子协议实现来保证这种扩展性。

总结

本文经过对WebSocket进行了一个全面的大体介绍,可以让你们对于WebSocket相关协议内容有一个初步的理解。

后续会持续对WebSocket协议进行翻译,有兴趣了解的同窗能够持续关注下。

相关文章
相关标签/搜索