WebSockets协议vs HTTP

有很多关于WebSocket和HTTP的博客和讨论,很多开发者和网站都强烈提倡WebSocket,但我仍然不明白为什么。

例如(WebSocket爱好者的参数):

HTML5 Web Sockets代表了Web通信的下一次发展——通过Web上的单个套接字操作的全双工双向通信通道。——websocket.org

HTTP支持流:请求正文流(你在上传大文件时使用它)和响应正文流。

在与WebSocket连接期间,客户端和服务器每帧交换数据,每帧交换数据2字节,而当您进行连续轮询时,HTTP报头的交换数据为8千字节。

为什么这2个字节不包括TCP和TCP协议开销?

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

这是约48字节的HTTP报头。

HTTP分块编码- 分块传输编码:

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协议?
193746 次浏览

你似乎认为WebSocket是HTTP的替代品。事实并非如此。这是一种延伸。

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

在WebSockets出现之前,JavaScript应用程序与服务器交互的唯一方法是通过XmlHttpRequest。但这些都有一个主要的缺点:除非客户机显式地请求数据,否则服务器无法发送数据。

但是新的WebSocket特性允许服务器随时发送数据。这使得基于浏览器的游戏能够以更低的延迟实现,并且无需使用AJAX长轮询或浏览器插件等丑陋的技巧。

那么为什么不使用普通的HTTP流请求和响应呢

在对另一个答案的注释中,您建议只异步传输客户端请求和响应体。

事实上,WebSockets基本上就是这样。从客户端打开WebSocket连接的尝试一开始看起来像一个HTTP请求,但是在头文件(Upgrade: websocket)中有一个特殊的指令告诉服务器开始以这种异步模式进行通信。WebSocket协议的初稿仅仅是一些握手,以确保服务器实际上理解客户端想要异步通信。但后来人们意识到,代理服务器可能会因此感到困惑,因为它们习惯了HTTP的常见请求/响应模型。发现针对代理服务器的潜在的攻击场景。为了防止这种情况,有必要让WebSocket流量看起来不像任何正常的HTTP流量。这就是为什么在协议的最终版本中引入了屏蔽键。

1)为什么WebSockets协议更好?

WebSockets更适合于涉及低延迟通信的情况,特别是客户端到服务器消息的低延迟。对于服务器到客户端数据,使用长连接和分块传输可以获得相当低的延迟。然而,这并不能解决客户端到服务器的延迟问题,因为这需要为每个客户端到服务器的消息建立一个新的连接。

你的48字节HTTP握手对于现实世界的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个字节)。延迟开销与头文件的大小无关,而是与解析/处理/存储这些头文件的逻辑有关。此外,TCP连接建立延迟可能是比每个请求的大小或处理时间更大的因素。

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

有努力重新设计HTTP协议,以实现更好的性能和更低的延迟,如SPDYHTTP 2.0QUIC。这将改善正常HTTP请求的情况,但WebSockets和/或WebRTC DataChannel的客户端到服务器数据传输的延迟可能仍然比HTTP协议低(或者它将以一种看起来很像WebSockets的模式使用)。

更新:

下面是一个考虑web协议的框架:

  • TCP:低级的、双向的、全双工的、有保证的顺序传输层。不支持浏览器(插件/Flash除外)。

  • HTTP 1.0: TCP分层的请求-响应传输协议。客户端发出一个完整的请求,服务器给出一个完整的响应,然后连接关闭。请求方法(GET、POST、HEAD)对于服务器上的资源具有特定的事务意义。

  • HTTP 1.1:保持HTTP 1.0的请求-响应性质,但允许连接在多个完整请求/完整响应时保持打开(每个请求一个响应)。在请求和响应中仍然有完整的头,但是连接被重用而没有关闭。HTTP 1.1还增加了一些额外的请求方法(OPTIONS, PUT, DELETE, TRACE, CONNECT),这些方法也具有特定的事务含义。然而,正如在HTTP 2.0草案提案的介绍中所指出的,HTTP 1.1管道没有被广泛部署,因此这极大地限制了HTTP 1.1解决浏览器和服务器之间延迟的效用。

  • 长轮询: sort of a“hack”;到HTTP(1.0或1.1),服务器不立即响应(或只响应部分报头)客户端请求。在服务器响应之后,客户端立即发送一个新请求(如果使用HTTP 1.1,则使用相同的连接)。

  • HTTP流媒体:多种技术(多部分/分块响应),允许服务器向单个客户端请求发送多个响应。W3C正在使用text/event-stream MIME类型将其标准化为服务器发送的事件。浏览器API(非常类似于WebSocket API)被称为EventSource API。

  • 彗星/服务器推送:这是一个涵盖性术语,包括长轮询和HTTP流。Comet库通常支持多种技术,以尝试最大化跨浏览器和跨服务器支持。

  • :建立在TCP上的传输层,使用HTTP友好的升级握手。与流式传输的TCP不同,WebSockets是基于消息的传输:消息在线路上进行分隔,并在传递到应用程序之前完整地重新组装。WebSocket连接是双向的、全双工的、长寿命的。在最初的握手请求/响应之后,没有事务语义,每条消息的开销也很小。客户端和服务器可以在任何时候发送消息,并且必须异步处理消息接收。

  • SPDY:谷歌发起的提议,使用更有效的有线协议扩展HTTP,但保持所有HTTP语义(请求/响应,cookie,编码)。SPDY引入了一种新的帧格式(带有长度前缀的帧),并指定了一种将HTTP请求/响应对分层到新的帧层的方法。头文件可以被压缩,并且在连接建立之后可以发送新的头文件。在浏览器和服务器中有SPDY的真实实现。

  • HTTP 2.0:具有与SPDY类似的目标:在保留HTTP语义的同时减少HTTP延迟和开销。当前的草案来源于SPDY,并定义了一个升级握手和数据帧,这与握手和帧的WebSocket标准非常相似。另一个HTTP 2.0草案提案(httpbiss -speed-mobility)实际上使用WebSockets作为传输层,并添加了SPDY多路复用和HTTP映射作为WebSocket扩展(WebSocket扩展是在握手期间协商的)。

  • WebRTC / CU-WebRTC:提议允许浏览器之间的点对点连接。这可能会降低平均和最大延迟通信,因为底层传输是SDP/数据报而不是TCP。这允许包/消息的无序传递,从而避免了由丢弃的包引起的TCP延迟峰值问题,从而延迟了所有后续包的传递(以保证有序传递)。

  • QUIC:是一个实验性协议,旨在降低TCP的web延迟。从表面上看,QUIC非常类似于在UDP上实现的TCP+TLS+SPDY。QUIC提供了等价于HTTP/2的多路复用和流量控制,等价于TLS的安全性,以及等价于TCP的连接语义、可靠性和拥塞控制。由于TCP是在操作系统内核和中间盒固件中实现的,因此对TCP进行重大更改几乎是不可能的。然而,由于QUIC是建立在UDP之上的,所以它没有这样的限制。QUIC是针对HTTP/2语义设计和优化的。

参考文献:

HTTP:

服务器发送的事件:

:

SPDY:

HTTP 2.0:

WebRTC:

QUIC:

对于TL;DR,这里有2美分和一个简单的版本来回答你的问题:

  1. WebSockets通过HTTP提供以下好处:

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

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

HTTP协议完全能够实现全双工通信;客户端执行带有分块编码传输的POST,服务器返回带有分块编码主体的响应,这是合法的。这将在初始化时删除头开销。

因此,如果你所追求的是全双工,同时控制客户端和服务器,并且对WebSockets的额外帧/特性不感兴趣,那么我认为HTTP是一种更简单的方法,具有更低的延迟/CPU(尽管延迟实际上只会以微秒或更短的时间为单位)。

为什么WebSockets协议更好?

我不认为我们可以把他们放在一起比较,比如谁更好。这不是一个公平的比较,因为他们正在解决两个不同的问题。他们的要求是不同的。这就像比较苹果和橘子一样。他们是不同的。

HTTP是一个请求-响应协议。客户端(浏览器)想要什么,服务器就给它。这是。如果客户端想要的数据很大,服务器可能会发送流数据以避免不必要的缓冲区问题。这里的主要需求或问题是如何从客户端发出请求,以及如何响应他们请求的资源(超文本)。这就是HTTP的亮点所在。

在HTTP中,只有客户端请求。服务器只响应。

WebSocket不是一个只有客户端可以请求的请求-响应协议。它是一个套接字(非常类似于TCP套接字)。意思是一旦连接打开,任何一方都可以发送数据,直到下划线TCP连接关闭。它就像一个普通的插座。与TCP套接字的唯一区别是WebSocket可以在web上使用。在web上,我们对普通套接字有很多限制。大多数防火墙会阻止HTTP使用的80和433以外的其他端口。代理和中介也会有问题。因此,为了使协议更容易部署到现有的基础设施WebSocket使用HTTP握手来升级。这意味着当第一次连接将要打开时,客户端发送一个HTTP请求告诉服务器“这不是HTTP请求,请升级到WebSocket协议”。

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

一旦服务器理解了请求并升级到WebSocket协议,就不再应用HTTP协议了。

所以我的答案是谁也不比谁强。它们完全不同。

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

好吧,我们也可以将所有的东西都命名为HTTP。但是我们可以吗?如果它们是两种不同的东西,我会喜欢两个不同的名字。Hickson和迈克尔•卡特也是如此。

常规REST API使用HTTP作为通信的底层协议,它遵循请求和响应范式,这意味着通信涉及客户端从服务器请求一些数据或资源,服务器对该客户端作出响应。但是,HTTP是一种无状态协议,因此每个请求-响应周期最终都必须重复报头和元数据信息。在频繁重复请求-响应周期的情况下,这会导致额外的延迟。

http

使用WebSockets,尽管通信仍然以初始的HTTP握手开始,但它会进一步升级以遵循WebSockets协议(即,如果服务器和客户端都符合该协议,因为不是所有实体都支持WebSockets协议)。

现在有了WebSockets,就有可能在客户端和服务器之间建立一个全双工的持久连接。这意味着与请求和响应不同,只要应用程序在运行(即它是持久的),连接就会保持打开,并且由于它是全双工的,双向同步通信是可能的,即现在服务器能够发起通信,并在新数据(客户端感兴趣的)可用时“推送”一些数据给客户端。

websockets

WebSockets协议是有状态的,允许您实现发布-订阅(或Pub/Sub)消息模式,这是实时技术中使用的主要概念,在实时技术中,您可以以服务器推送的形式获得新的更新,而无需客户端重复请求(刷新页面)。这类应用的例子包括优步汽车的位置跟踪、推送通知、股票市场价格实时更新、聊天、多人游戏、在线协作工具等。

你可以在Websockets上查看一篇深入的文章,它解释了这个协议的历史,它是如何形成的,它的用途是什么,以及你如何自己实现它。

这是我做的一个关于WebSockets的演示视频,以及它们与使用常规REST api的区别:标准化和利用数据流的指数级增长