WebSockets协议与HTTP


329

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

例如(网络套接字爱好者的参数):

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

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

与WebSocket建立连接期间,客户端和服务器每帧交换数据,每帧2字节,而连续轮询时HTTP头为8千字节。

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

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

这是〜48个字节的http标头。

http分块编码-https : //en.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协议?

2
你的问题是什么?
乔纳斯(Jonas)2013年

@ Jonas,1)为什么websockets协议更好?2)为什么实施它而不是更新http协议?3)为什么如此推广websocket?
2013年

@JoachimPileborg,对于桌面应用程序,也可以使用TCP套接字或http来完成;并且您必须使用WebRTC来进行网站的浏览器到浏览器通信
4esn0k 2013年

@JoachimPileborg,它是用于浏览器到浏览器的
webRTC

@ 4esn0k,WS并不是更好,它们是不同的,并且对于某些特定任务来说更好。3)这是人们应该意识到的新功能,并为网络打开了新的可能性
乔纳斯(Jonas)2013年

Answers:


490

1)为什么WebSockets协议更好?

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

对于实际的HTTP浏览器连接来说,您的48字节HTTP握手是不现实的,在实际的HTTP浏览器连接中,作为请求的一部分(双向)通常发送几千字节的数据,其中包括许多标头和cookie数据。这是使用Chrome的请求/响应的示例:

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

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和WebSocket都具有相同大小的初始连接握手,但是对于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解决浏览器和服务器之间的延迟的实用性。
  • 长轮询:对HTTP(1.0或1.1)的一种“破解”,其中服务器不会立即响应客户端请求(或仅部分响应标头)。服务器响应后,客户端立即发送新请求(如果通过HTTP 1.1,则使用相同的连接)。
  • HTTP流:多种技术(多部分/块响应),这些技术允许服务器对单个客户端请求发送多个响应。W3C正在使用MIME类型将其标准化为服务器发送的事件text/event-stream。浏览器API(与WebSocket API非常相似)称为EventSource API。
  • 彗星/服务器推送:这是一个概括性术语,包括长轮询和HTTP流。彗星库通常支持多种技术,以尝试并最大化跨浏览器和跨服务器的支持。
  • WebSockets:传输层内置的TCP,使用HTTP友好的Upgrade握手。与TCP(一种流传输)不同,WebSockets是一种基于消息的传输:消息在网络上是定界的,并在交付给应用程序之前被完全重组。WebSocket连接是双向的,全双工的且寿命长。在初始握手请求/响应之后,没有事务语义,每个消息的开销也很小。客户端和服务器可以随时发送消息,并且必须异步处理消息接收。
  • SPDY:由Google发起的一项提案,旨在使用更有效的有线协议扩展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减少Web延迟。从表面上看,QUIC与在UDP上实现的TCP + TLS + SPDY非常相似。QUIC提供等效于HTTP / 2的多路复用和流控制,等效于TLS的安全性以及等效于TCP的连接语义,可靠性和拥塞控制。由于TCP是在操作系统内核和中间盒固件中实现的,因此对TCP进行重大更改几乎是不可能的。但是,由于QUIC是建立在UDP之上的,因此不受任何限制。QUIC针对HTTP / 2语义进行了设计和优化。

参考文献


1
>>但是,这对客户端到服务器的延迟没有帮助,这需要为每个客户端到服务器的消息建立一个新的连接。-响应主体的流式传输如何?我知道,XMLHttpRequest API不允许这样做,但是它存在。通过流式传输到服务器,您可以从客户端流式传输。
13年

8
@Philipp,他问了一个问题,无论如何我一直想彻底研究和记录文件。WebSockets与其他基于HTTP的机制的问题经常出现,因此现在有一个很好的链接参考。但是,是的,提问者似乎很可能在寻找证据来支持关于WebSockets vs HTTP的先入为主的观念,特别是因为他从未选择答案也未授予赏金。
kanaka 2013年

9
非常感谢您对协议进行了非常精确的概述。
Martin Meeser 2014年

2
@WardC caniuse.com提供浏览器兼容性信息(包括移动设备)。
kanaka

3
@ www139,不,在WebSocket协议级别,连接保持打开状态,直到一侧或另一侧关闭连接为止。您可能还需要担心TCP超时(任何基于TCP的协议都存在的问题),但是每分钟或两分钟的任何流量都会使连接保持打开状态。实际上,WebSocket协议定义指定了ping / pong帧类型,即使没有该类型,您也可以发送一个字节(加上两个字节的标头),并使连接保持打开状态。每两分钟2-3个字节根本不会对带宽造成重大影响。
kanaka

130

您似乎以为WebSocket可以替代HTTP。它不是。这是一个扩展。

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

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

但是新的WebSocket功能允许服务器在需要时发送数据。这允许以低得多的延迟来实现基于浏览器的游戏,而不必使用诸如AJAX长轮询或浏览器插件之类的丑陋骇客。

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

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

实际上,WebSocket基本上就是这样。尝试从客户端打开WebSocket连接的尝试起初看起来像是HTTP请求,但是标头中的特殊指令(升级:websocket)告诉服务器开始以这种异步模式进行通信。WebSocket协议的初稿仅此而已,并且进行了一些握手,以确保服务器真正了解客户端要异步通信。但是后来意识到,代理服务器会对此感到困惑,因为它们习惯于HTTP的常规请求/响应模型。一个潜在的攻击场景中对代理服务器被发现。为防止这种情况,必须使WebSocket通信看起来不同于任何普通的HTTP通信。这就是为什么在其中引入了屏蔽键的原因协议的最终版本


>>除非客户明确要求,否则服务器无法发送数据。Web浏览器应启动WebSockets连接...与XMLHttpRequest相同
4esn0k

18
@ 4esn0k浏览器确实启动了websocket连接。但是建立后,双方都可以随时发送数据。XmlHttpRequest并非如此。
菲利普

1
为什么使用HTTP无法做到这一点?
13年

4
@Philipp,游戏是WebSocket发光的一个很好的例子。但是,这不是您获得最大胜利的来自服务器的实时数据。使用HTTP流/长期连接,您可以获得几乎与服务器->客户延迟一样好的延迟。借助长期保留的请求,服务器可以在有数据时有效地发送数据,因为客户端已经发送了请求,并且服务器“保留了请求”直到有数据为止。WebSocket的最大优势在于客户端->服务器延迟(因此是往返)。客户端能够在任何时候发送请求而没有请求开销是真正的关键。
kanaka

1
@Philipp,另一个注意事项:除了XMLHttpRequest和WebSockets(用于JavaScript)与服务器交互之外,还有其他方法,包括隐藏的iframe和长轮询脚本标签。有关更多详细信息,请参见Comet Wikipedia页面:en.wikipedia.org/wiki/Comet_(编程)
kanaka

27

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

http

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

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

网络套接字

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

您可以在Websockets上深入阅读有关该协议的历史,该协议的产生方式,用途以及如何自己实现的文章。

这是我做过一个关于WebSockets的演示的视频,它与使用常规REST API有何不同:标准化并利用数据流的指数增长


24

对于TL; DR,这是2美分,一个简单的版本可以解决您的问题:

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

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


3
重要的是您在比较中提到有状态和无状态(Y)
Utsav T

15

为什么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。但是我们可以吗?如果它们是两个不同的东西,我将首选两个不同的名称。希克森和迈克尔卡特也是


6

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

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

因此,如果您要查找的是全双工的,同时控制客户端和服务器,并且对websocket的额外帧/功能不感兴趣,那么我认为HTTP是一种更简单的方法,具有较低的延迟/ CPU(尽管延迟两者之间的差异实际上只有微秒或更短)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.