WebSockets协议vs HTTP

关于websocket和HTTP有很多博客和讨论,许多开发人员和站点强烈主张websocket,但我仍然不明白为什么。

例如(websocket爱好者的论点):

HTML5 Web Sockets代表了Web通信的下一个发展 – 一种全双工的双向通信通道,通过Web上的一个套接字进行操作。 ( http://www.websocket.org/quantum.html )

HTTP支持stream:请求正文stream(您正在使用它,而上传大文件)和响应正文stream。

在与WebSocketbuild立连接的过程中,客户端和服务器之间交换每帧2个字节的数据,而在进行连续轮询时,与8千字节的http头相比。

为什么那2个字节不包含tcp和tcp协议的开销?

GET /about.html HTTP/1.1 Host: example.org 

这是约48个字节的http头。

http分块编码 – http://ru.wikipedia.org/wiki/Chunked_transfer_encoding :

 23 This is the data in the first chunk 1A and this is the second one 3 con 8 sequence 0 
  • 所以,每个块的开销并不大。

而且这两种协议都是通过TCP协议工作的,因此所有长连接的TCP问题仍然存在。

题:

  1. 为什么websockets协议更好?
  2. 为什么实现而不是更新http协议?

1)为什么WebSockets协议更好?

对于涉及低延迟通信的情况,特别是对于客户端到服务器消息的低延迟,WebSocket更好。 对于服务器到客户端的数据,使用长连接和分块传输可以获得相当低的延迟。 但是,这不会帮助客户端到服务器延迟,这需要为每个客户端到服务器的消息build立新的连接。

对于真实世界的HTTP浏览器连接来说,48字节的HTTP握手是不现实的,在这种连接中,经常会有数千字节的数据作为请求的一部分(包括两个方向)发送,包括许多标头和cookie数据。 以下是使用Chrome的请求/响应示例:

示例请求(包含Cookie数据的2800字节,不含Cookie数据的490字节):

 GET / HTTP/1.1 Host: www.cnn.com Connection: keep-alive Cache-Control: no-cache Pragma: no-cache Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.68 Safari/537.17 Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 Cookie: [[[2428 byte of cookie data]]] 

响应示例(355字节):

 HTTP/1.1 200 OK Server: nginx Date: Wed, 13 Feb 2013 18:56:27 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive Set-Cookie: CG=US:TX:Arlington; path=/ Last-Modified: Wed, 13 Feb 2013 18:55:22 GMT Vary: Accept-Encoding Cache-Control: max-age=60, private Expires: Wed, 13 Feb 2013 18:56:54 GMT Content-Encoding: gzip 

HTTP和WebSockets都具有相同大小的初始连接握手,但是通过WebSocket连接,初始握手会执行一次,然后小消息只有6个字节的开销(头为2,掩码值为4)。 延迟开销与标题的大小没有多大关系,而是从逻辑来parsing/处理/存储这些标题。 另外,TCP连接build立延迟可能比每个请求的大小或处理时间要大。

2)为什么实现而不是更新HTTP协议?

有人努力重新deviseHTTP协议,以获得更好的性能和更低的延迟,如SPDY , HTTP 2.0和QUIC 。 这将改善正常的HTTP请求的情况,但WebSocket和/或WebRTC DataChannel对于客户端到服务器的数据传输的延迟可能比HTTP协议的延迟更低(或者将以与WebSockets类似的模式无论如何)。

更新

这是一个思考networking协议的框架:

  • TCP :低级别,双向,全双工和有保证的命令传输层。 没有浏览器支持(除了通过插件/ Flash)。
  • HTTP 1.0 :在TCP上分层的请求 – 响应传输协议。 客户端发出一个完整的请求,服务器给出一个完整的响应,然后连接closures。 请求方法(GET,POST,HEAD)对于服务器上的资源具有特定的事务性意义。
  • HTTP 1.1 :保持HTTP 1.0的请求 – 响应性质,但允许连接保持打开状态,以执行多个完整请求/完整响应(每个请求一个响应)。 在请求和响应中仍然有完整的头文件,但连接被重新使用并且没有closures。 HTTP 1.1还添加了一些额外的请求方法(OPTIONS,PUT,DELETE,TRACE,CONNECT),这些方法也具有特定的事务含义。 但是,正如HTTP 2.0草案的介绍中所指出的那样,HTTP 1.1pipe道并没有被广泛部署,所以这极大地限制了HTTP 1.1解决浏览器和服务器之间的延迟的效用。
  • 长时间轮询 :对HTTP(1.0或1.1)进行“黑客攻击”,服务器不会立即响应(或只响应部分头部响应)客户端请求。 服务器响应后,客户端立即发送一个新的请求(如果通过HTTP 1.1使用相同的连接)。
  • HTTP streaming :多种技术(多部分/分块响应),允许服务器向单个客户端请求发送多个响应。 W3C使用text/event-stream MIMEtypes将其标准化为Server-Sent Events 。 浏览器API(与WebSocket API非常相似)称为EventSource API。
  • Comet /服务器推送 :这是一个涵盖长时间轮询和HTTPstream媒体的总称。 彗星库通常支持多种技术来尝试和最大化跨浏览器和跨服务器支持。
  • WebSockets :使用HTTP友好的内置TCP的传输层升级握手。 与TCP是一种stream式传输不同的是,WebSockets是一种基于消息的传输:消息在networking上被分隔,并在传递到应用程序之前被全部重新组装。 WebSocket连接是双向的,全双工和长期的。 在初始握手请求/响应之后,没有事务性语义,并且每消息开销很小。 客户端和服务器可以随时发送消息,并且必须asynchronous处理消息接收。
  • SPDY :Google发起的使用更有效的有线协议来扩展HTTP的提议,但是保持所有HTTP语义(请求/响应,cookie,编码)。 SPDY引入了一种新的成帧格式(带长度前缀的帧),并指定了将HTTP请求/响应对分层到新的成帧层的方法。 在build立连接之后,可以压缩标题并发送新的标题。 在浏览器和服务器中有SPDY的真实世界的实现。
  • HTTP 2.0 :与SPDY具有相似的目标:减lessHTTP延迟和开销,同时保留HTTP语义。 目前的草案来源于SPDY,并定义了一个与WebSocket握手和组帧的标准非常相似的升级握手和数据组帧。 另一个HTTP 2.0草案提案(httpbis-speed-mobility)实际上将WebSocket用于传输层,并将SPDY多路复用和HTTP映射作为WebSocket扩展(WebSocket扩展在握手期间进行协商)。
  • WebRTC / CU-WebRTC :允许浏览器之间进行点对点连接的build议。 这可以实现较低的平均和最大延迟通信,因为底层传输是SDP /数据报而不是TCP。 这允许分组/消息的无序传送,这避免了由丢弃的分组引起的延迟尖峰的TCP问题,这延迟了所有后续分组的传送(以保证按顺序传送)。
  • QUIC :是一个旨在减lessTCP延迟的实验性协议。 从表面上看,QUIC与UDP上实现的TCP + TLS + SPDY非常相似。 QUIC提供等效于HTTP / 2的复用和stream量控制,等同于TLS的安全性,以及与TCP等同的连接语义,可靠性和拥塞控制。 由于TCP是在操作系统内核和中间件固件中实现的,所以对TCP进行重大改变几乎是不可能的。 但是,由于QUIC是build立在UDP之上的,所以没有这样的限制。 QUIC针对HTTP / 2语义进行了devise和优化。

参考文献

  • HTTP
    • 维基百科HTTP页面
    • W3C HTTP相关的草稿/协议列表
    • IETF HTTP / 1.1和HTTP / 2.0草稿列表
  • 服务器发送的事件
    • W3C服务器发送的事件/事件源候选推荐
    • W3C服务器发送的事件/事件源草案
  • WebSockets
    • IETF RFC 6455 WebSockets协议
    • IETF RFC 6455 WebSocket勘误表
  • SPDY
    • IETF SPDY草案
  • HTTP 2.0
    • IETF HTTP 2.0 httpbis-http2草案
    • IETF HTTP 2.0 httpbis-speed-mobility草案
    • IETF httpbis-network-friendly草案 – 一个早期的HTTP 2.0相关的提案
  • WebRTC
    • W3C WebRTC API草案
    • IETF WebRTC草案列表
    • IETF WebRTC概述草案
    • IETF WebRTC DataChannel草案
    • 微软CU-WebRTCbuild议开始页面
  • QUIC
    • QUIC Chrominum项目
    • IETF QUIC草案

你似乎认为WebSocket是HTTP的替代品。 不是这样。 这是一个扩展。

WebSockets的主要用例是在Web浏览器中运行并从服务器接收实时数据的Javascript应用程序。 游戏就是一个很好的例子。

在WebSockets之前,JavaScript应用程序与服务器交互的唯一方法是通过XmlHttpRequest 。 但是这些都有一个主要的缺点:服务器不能发送数据,除非客户端明确要求数据。

但新的WebSocketfunction允许服务器随时发送数据。 这允许以低得多的延迟实现基于浏览器的游戏,而不必使用AJAX长轮询或浏览器插件等丑恶的黑客。

那么为什么不使用普通的HTTP来传输stream请求和响应

在对另一个答案的评论中,你build议只是asynchronousstream式传输客户端请求和响应主体。

事实上,WebSockets基本上是这样的。 试图从客户端打开一个WebSocket连接看起来就像是一个HTTP请求,但头部的一个特殊指令(Upgrade:websocket)告诉服务器以这种asynchronous模式开始通信。 WebSocket协议的初稿并不仅仅是这个,还有一些握手,以确保服务器真正理解客户端想要asynchronous通信。 但是后来才意识到,代理服务器会被这个混淆,因为它们习惯于HTTP通常的请求/响应模式。 发现了针对代理服务器的潜在攻击情况 。 为了防止这种情况,有必要使WebSocketstream量看起来不像任何正常的HTTPstream量。 这就是为什么在协议的最终版本中引入了掩码密钥。

对于TL,DR,这里是2美分,对于你的问题更简单的版本:

  1. WebSockets通过HTTP提供这些好处:

    • 在连接期间持续有状态的连接
    • 低延迟:服务器/客户端之间的近实时通信,因为不需要像HTTP那样为每个请求重新build立连接的开销。
    • 全双工:服务器和客户端可以同时发送/接收
  2. WebSocket和HTTP协议是为了解决不同的问题而devise的,IE WebSocket旨在改进双向通信,而HTTP则被devise成无状态,使用请求/响应模型进行分发。 除了由于遗留原因(防火墙/代理渗透)共享端口,将它们组合成一个协议没有太大的共同点。

其他的答案似乎并没有涉及到这方面的一个关键方面,那就是你没有提到需要支持Web浏览器作为客户端。 上面的纯HTTP的大部分限制都假设你将使用浏览器/ JS实现。

HTTP协议完全能够进行全双工通信; 让客户端执行分块编码传输的POST和服务器以分块编码体返回响应是合法的。 这将在初始时间删除头部开销。

所以,如果你正在寻找的是全双工,控制客户端和服务器,并没有兴趣在额外的框架/ websockets的function,那么我认为HTTP是一个更简单的方法与更低的延迟/ CPU(虽然潜伏实际上只有几微秒或更less)。