WebSockets协议与HTTP

4es*_*n0k 297 ajax comet http websocket

关于websocket和HTTP有很多博客和讨论,许多开发人员和网站都强烈支持websockets,但我仍然无法理解为什么.

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

HTML5 Web套接字代表了Web通信的下一个发展 - 一种全双工双向通信通道,通过Web上的单个插槽运行.(http://www.websocket.org/quantum.html)

HTTP支持流媒体:请求正文流(您在上传大文件时使用它)和响应正文流.

在与WebSocket连接期间,客户端和服务器每帧交换2个字节的数据,而连续轮询时则为8千字节的http头.

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

GET /about.html HTTP/1.1
Host: example.org
Run Code Online (Sandbox Code Playgroud)

这是~48字​​节的http标头.

http chunked编码 - 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
Run Code Online (Sandbox Code Playgroud)
  • 因此,每个块的开销并不大.

这两个协议都可以在TCP上运行,因此所有与长期连接的TCP问题仍然存在.

题:

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

kan*_*aka 457

1)为什么WebSockets协议更好?

WebSockets适用于涉及低延迟通信的情况,尤其适用于客户端到服务器消息的低延迟.对于服务器到客户端数据,使用长连接和分块传输可以获得相当低的延迟.但是,这对客户端到服务器延迟没有帮助,这需要为每个客户端到服务器消息建立新连接.

对于真实世界的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]]]
Run Code Online (Sandbox Code Playgroud)

响应示例(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
Run Code Online (Sandbox Code Playgroud)

HTTP和WebSockets都具有相同大小的初始连接握手,但是使用WebSocket连接时,初始握手执行一次,然后小消息只有6个字节的开销(标头为2,掩码值为4).延迟开销不是从头的大小,而是从解析/处理/存储这些头的逻辑.此外,TCP连接建立延迟可能比每个请求的大小或处理时间更重要.

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

人们正在努力重新设计HTTP协议以实现更好的性能和更低的延迟,例如SPDY,HTTP 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在解决浏览器和服务器之间延迟方面的效用.
  • 长轮询:对HTTP(1.0或1.1)的"黑客攻击",其中服务器不立即响应(或仅部分响应标头)响应客户端请求.在服务器响应之后,客户端立即发送新请求(如果通过HTTP 1.1,则使用相同的连接).
  • HTTP流式传输:各种技术(多部分/分块响应),允许服务器向单个客户端请求发送多个响应.W3C 使用MIME类型将其标准化为服务器发送事件text/event-stream.浏览器API(与WebSocket API非常相似)称为EventSource API.
  • Comet/server push:这是一个包含长轮询和HTTP流传输的总称.Comet库通常支持多种技术来尝试并最大化跨浏览器和跨服务器支持.
  • WebSockets:使用HTTP友好升级握手的传输层内置TCP.与作为流传输的TCP不同,WebSockets是基于消息的传输:消息在线路上分隔,并在传送到应用程序之前完全重新组装.WebSocket连接是双向的,全双工的并且是长期存在的.在初始握手请求/响应之后,没有事务语义,并且每个消息开销很少.客户端和服务器可以随时发送消息,并且必须异步处理消息接收.
  • SPDY:谷歌发起的提议,使用更有效的有线协议扩展HTTP,但保持所有HTTP语义(请求/响应,cookie,编码).SPDY引入了一种新的成帧格式(带有长度前缀的帧),并指定了将HTTP请求/响应对分层到新的成帧层的方法.可以压缩标头,并在建立连接后发送新标头.在浏览器和服务器中存在SPDY的现实世界实现.
  • HTTP 2.0:具有与SPDY类似的目标:在保留HTTP语义的同时减少HTTP延迟和开销.当前草案源自SPDY并定义了升级握手和数据成帧,这与握手和成帧的WebSocket标准非常相似.另一个HTTP 2.0草案提案(httpbis-speed-mobility)实际上使用WebSockets作为传输层,并将SPDY多路复用和HTTP映射添加为WebSocket扩展(在握手期间协商WebSocket扩展).
  • WebRTC/CU-WebRTC:允许浏览器之间进行点对点连接的提议.这可以实现较低的平均和最大等待时间通信,因为底层传输是SDP /数据报而不是TCP.这允许无序地传送分组/消息,这避免了由丢弃的分组引起的延迟尖峰的TCP问题,这延迟了所有后续分组的传送(以保证有序传送).
  • QUIC:是一个旨在减少TCP延迟的实验性协议.从表面上看,QUIC与UDP上实现的TCP + TLS + SPDY非常相似.QUIC提供与HTTP/2等效的多路复用和流控制,相当于TLS的安全性,以及与TCP等效的连接语义,可靠性和拥塞控制.由于TCP是在操作系统内核和中间件固件中实现的,因此对TCP进行重大更改几乎是不可能的.但是,由于QUIC建立在UDP之上,因此没有这种限制.QUIC是针对HTTP/2语义设计和优化的.

参考文献:

  • 非常感谢您对协议的非常精确和精确的概述. (9认同)
  • @Philipp,他问了一个问题,我一直想要彻底研究和记录.WebSockets与其他基于HTTP的机制的问题经常出现,但现在有一个很好的链接指向.但是,似乎提问者似乎正在寻找证据来支持关于WebSockets与HTTP的先入为主的观念,特别是因为他从未选择答案或授予赏金. (8认同)
  • >> 但是,这对客户端到服务器的延迟没有帮助,这需要为每个客户端到服务器的消息建立新的连接。- 响应体的流呢?我知道,XMLHttpRequest API 不允许这样做,但它是存在的。通过流式传输到服务器,您可以从客户端流式传输。 (2认同)
  • @WardC http://caniuse.com提供浏览器兼容性信息(包括移动设备). (2认同)
  • @ www139,不,在WebSocket协议级别,连接保持打开,直到一侧或另一侧关闭连接.您可能还需要担心TCP超时(任何基于TCP的协议的问题),但每分钟或两分钟的任何类型的流量都会使连接保持打开状态.实际上,WebSocket协议定义指定了ping/pong帧类型,尽管如此,你可以发送一个字节(加上两个字节的头)并保持连接打开.每两分钟2-3个字节根本不会对带宽产生重大影响. (2认同)

Phi*_*ipp 122

您似乎假设WebSocket是HTTP的替代品.它不是.这是一个扩展.

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

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

但新的WebSocket功能允许服务器随时发送数据.这允许实现具有低得多的延迟的基于浏览器的游戏,而不必使用诸如AJAX长轮询或浏览器插件之类的丑陋黑客.

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

在对另一个答案的评论中,您建议只是异步地流式传输客户端请求和响应正文.

实际上,WebSockets基本上就是这样.尝试从客户端打开WebSocket连接首先看起来像HTTP请求,但标题中的特殊指令(Upgrade:websocket)告诉服务器开始以此异步模式进行通信.WebSocket协议的初稿并不仅仅是那些以及确保服务器实际理解客户端想要异步通信的一些握手.但后来人们意识到代理服务器会被它混淆,因为它们习惯于HTTP的通常请求/响应模型.一个潜在的攻击场景中对代理服务器被发现.为了防止这种情况,有必要使WebSocket流量看起来不像任何普通的HTTP流量.这就是为什么在协议的最终版本中引入了掩码密钥的原因.

  • @ 4esn0k浏览器确实启动了websocket连接.但在建立之后,双方都可以随时发送数据.XmlHttpRequest不是这种情况. (17认同)
  • @Philipp,游戏是WebSockets闪耀的好例子.但是,从服务器获得最大胜利的不是实时数据.使用HTTP流/长连接可以获得几乎同样好的服务器 - >客户端延迟.通过长时间保持的请求,服务器可以在有数据时有效地发送,因为客户端已经发送了请求,服务器"持有请求"直到它有数据.WebSockets的最大胜利是客户端 - >服务器延迟(因此往返).客户端能够在没有请求开销的情况下随时发送是真正的关键. (3认同)
  • 为什么这在 H​​TTP 中是不可能的? (2认同)

Dev*_*evy 19

对于TL; DR,这里有2美分和更简单的版本问题:

  1. WebSockets通过HTTP提供以下优势:

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

  • 重要的是你在比较中提到了有状态和无状态这个术语(Y) (2认同)

小智 17

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

http

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

现在使用WebSockets,可以在客户端和服务器之间建立全双工和持久连接。这意味着,与请求和响应不同的是,只要应用程序正在运行(即,它是持久性的),连接就保持打开状态,并且由于它是全双工的,因此可以进行双向同步通信,即服务器现在可以启动进行通信并在新数据(客户端感兴趣的)可用时将某些数据“推送”给客户端。

网络套接字

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

您可以查看有关Websockets的深入探讨文章,其中介绍了该协议的历史,它的产生方式,用途以及如何自己实现。

这是我所做的有关WebSocket的演示的视频,以及与使用常规REST API的区别:标准化并利用数据流的指数增长

  • 非常感谢 @Shrushtika 的清晰解释。 (4认同)

Fra*_*Xho 14

为什么websockets协议更好?

我认为我们不能将它们并排比较,就像谁更好.这不公平比较仅仅是因为他们正在解决两个不同的问题.他们的要求是不同的.这就像比较苹果和橙子.它们是不同的.

HTTP是请求 - 响应协议.客户端(浏览器)需要一些东西,服务器给它.那是.如果数据客户端想要的很大,服务器可能会发送流数据以消除不需要的缓冲区问题.这里的主要要求或问题是如何从客户端发出请求以及如何响应他们请求的资源(hybertext).这就是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
Run Code Online (Sandbox Code Playgroud)

一旦服务器理解了请求并升级到websocket协议,HTTP协议就不再适用了.

所以我的答案是两者都不比彼此好.它们完全不同.

为什么要实现而不是更新http协议?

好吧,我们也可以在名为HTTP的名称下创建所有内容.但是我们呢?如果它们是两个不同的东西,我会更喜欢两个不同的名字.希克森和迈克尔卡特也是如此.


par*_*ty3 6

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

HTTP协议完全能够进行全双工通信; 让客户端使用分块编码传输执行POST是合法的,并且服务器返回具有分块编码主体的响应.这将在初始时删除标头开销.

因此,如果您正在寻找的是全双工,控制客户端和服务器,并且对websockets的额外框架/功能不感兴趣,那么我认为HTTP是一种更简单的方法,具有更低的延迟/ CPU(尽管延迟实际上只有微秒或更短的差异.)