WebSockets与服务器发送的事件/ EventSource


838

两个WebSocket服务器发送的事件能够将数据推送到浏览器。在我看来,它们似乎是竞争技术。它们之间有什么区别?您何时会选择一个?


2
不知道您如何看待他们的竞争。一种是同步的,可以/将用于近实时数据传输,而另一种是异步的,并且可以用于完全不同的目的(有效地从服务器端应用程序发送类似Toast的消息)。
Brian Driscoll

54
WebSockets是双向的,它可以将数据发送到服务器。
Andre Backlund

13
我真正喜欢SSE的一件事是,很容易进行故障排除...只需使用打开对SSE服务器的请求curl。由于它只是HTTP上的文本格式,因此很容易看到发生了什么。
山姆

7
@BrianDriscoll-异步/同步-哪个?据我了解,两者都可以启用异步传输?
戴夫·埃弗里特

5
SSE在IE上不起作用,websockets在IE上起作用
Tyler Gillies 2015年

Answers:


977

Websocket和SSE(服务器发送事件)都能够将数据推送到浏览器,但是它们不是竞争技术。

Websockets连接既可以将数据发送到浏览器,也可以从浏览器接收数据。可以使用websockets的应用程序的一个很好的例子是聊天应用程序。

SSE连接只能将数据推送到浏览器。在线股票报价或Twitter的更新时间表或提要是可以从SSE中受益的应用程序的很好示例。

在实践中,由于SSE可以完成的所有事情也都可以通过Websockets完成,因此Websockets得到了更多的关注和喜爱,并且与SSE相比,更多的浏览器支持Websockets。

但是,对于某些类型的应用程序而言,它可能会显得过大,并且使用诸如SSE之类的协议可以更轻松地实现后端。

此外,可以将SSE填充到不仅使用JavaScript本身不支持它的旧版浏览器中。可以在Modernizr github页面上找到SSE polyfills的一些实现。

陷阱:

  • SSE受最大打开连接数的限制,这在打开各种选项卡时特别麻烦,因为该限制是针对每个浏览器的,并且设置为一个非常低的数字(6)。该问题在ChromeFirefox中被标记为“无法解决” 。此限制是针对每个浏览器+域的,因此这意味着您可以在所有选项卡上打开6个SSE连接,并在上面打开www.example1.com另外6个SSE连接www.example2.com(感谢Phate)。
  • 只有WS可以传输二进制数据和UTF-8,而SSE限于UTF-8。(感谢Chado Nihi)。
  • 某些具有数据包检查功能的企业防火墙在处理WebSockets时遇到问题(Sophos XG Firewall,WatchGuard,McAfee Web Gateway)。

HTML5Rocks在SSE上有一些很好的信息。从该页面:

服务器发送的事件与WebSockets

为什么选择通过WebSockets发送服务器发送的事件?好问题。

SSE被遮盖的原因之一是因为后来的API(如WebSocket)提供了更丰富的协议来执行双向全双工通信。对于游戏,消息传递应用程序以及需要双向双向实时更新的情况,拥有双向通道更具吸引力。但是,在某些情况下,不需要从客户端发送数据。您只需要某些服务器操作的更新即可。几个例子是朋友的状态更新,股票行情自动收录器,新闻提要或其他自动数据推送机制(例如,更新客户端Web SQL数据库或IndexedDB对象存储)。如果您需要将数据发送到服务器,则XMLHttpRequest始终是朋友。

SSE通过传统的HTTP发送。这意味着它们不需要特殊的协议或服务器实现即可正常工作。另一方面,WebSockets需要全双工连接和新的Web Socket服务器来处理协议。此外,服务器发送的事件具有WebSocket设计上缺少的各种功能,例如自动重新连接,事件ID和发送任意事件的功能。


TLDR摘要:

SSE相对于Websockets的优势:

  • 通过简单的HTTP而不是自定义协议进行传输
  • 可以用JavaScript进行多填充,以将SSE“反向移植”到尚不支持的浏览器。
  • 内置对重新连接和事件ID的支持
  • 更简单的协议
  • 公司防火墙进行数据包检查没有问题

Websockets相对于SSE的优势:

  • 实时,双向通讯。
  • 在更多浏览器中的本机支持

SSE的理想用例:

  • 股票行情自动收录
  • Twitter提要更新
  • 通知浏览器

SSE陷阱:

  • 没有二进制支持
  • 最大开放连接数限制

131
使用SSE完全可以进行聊天-您可以使用常规POST将消息发送到服务器。仅当您实现chat a'la Google Wave时才需要WebSockets。
Kornel

135
的确,聊天和其他实时应用程序可以使用SSE完成。但是,这需要“带外”进行POST答复,即,这不受SSE协议控制,对于SSE和Websocket之间的区别的基本说明,它似乎不是一个好例子。您可以使用基本HTTP每秒对服务器进行一次轮询并发布新回复来实现聊天。这并不意味着它是最好/最优雅的方式。
Alex Recarey

14
我认为pomeL的解决方案在大多数情况下是一个很好的折衷方案,因为JS始终可以通过AJAX POST将内容“推送”到服务器。根据我的经验,主要的问题通常是JS需要轮询新信息,但是SSE会处理这些问题。:D
Jacob Pritchett

12
@MattDiPasquale Wave会在您键入时分别发送每个键,而不是一次发送完整消息。1次击键需要200字节的POST开销,而WebSocket大约需要6字节。
Kornel

9
说它们不是竞争性技术,然后描述它们都可以用于实现相似的解决方案似乎有些奇怪。我想说,这使他们竞争。
亚历克斯(Alex)

115

根据caniuse.com:

您可以使用仅客户端的polyfill将对SSE的支持扩展到许多其他浏览器。WebSockets不太可能这样。一些EventSource polyfills:

如果需要支持所有浏览器,请考虑使用诸如web-socket-jsSignalRsocket.io之类的库,该库支持多种传输方式,例如WebSockets,SSE,Forever Frame和AJAX长轮询。这些通常也需要修改服务器端。

从以下位置了解有关SSE的更多信息:

从以下位置了解有关WebSocket的更多信息:

其他差异:

  • WebSockets支持任意二进制数据,SSE仅使用UTF-8

3
我想指出的是,2016年,全球95%以上的用户本机支持WebSockets。所有浏览器和设备都已支持WebSocket超过4年。如果不支持,Socket.IO将回退到AJAX长轮询,并为您处理模拟WebSockets的复杂性,这使支持率达到了100%。如果您在2016年使用的不是WebSockets,那您使用的是过时的技术。
尼克·斯蒂尔

3
@NickSteele这是胡说八道的声明。如果它们满足您的用例,那么依靠较旧的标准就可以了,这并不意味着什么都已过时。这只是一个不同的标准。例如:XHR仍然可以执行Fetch API无法完成的许多工作,因此它并不落伍。这是不同的。我过去曾经使用过WS,但是从经验中知道,人们可能会以噪声企业防火墙的形式遇到障碍,当它不了解WS时就会阻止请求。SSE的工作效率极高,易于理解,可实现且易于调试。对于我们的单向数据流,它是完美的。
oligofren

@oligofren无需发誓。如果某种东西被设计用来代替以前的版本,并且从定义上说,它在各个方面都得到了业界的认可和更好,那么旧方法已经过时了。就像原始的iPhone已过时一样,XHR也是如此。XHR在Firefox,Chrome,第一个iPhone之前出现,在YouTube,Netflix,Facebook甚至MySpace之前出现。当XHR出现时,Windows 98是最好的操作系统,AOL是最好的提供程序,甚至不存在JSON。WebSockets在十年前取代了XHR。如果使用WS遇到障碍,则导致障碍的原因也已过时。没有任何理由要落后那么远。
尼克·斯蒂尔

4
然后用夸张的方式替换BS,然后:-) WS不能替代XHR / HTTP,就像无人机可以用于送货车一样。这是不同的用例。WS不是HTTP,具有不同的优点。如果尝试的话,最终会(在较差的程度上)在用户空间中重新实现HTTP。另外,您还暗示着没有事实的事实:WS只是支持服务器推送的双向协议。我从未见过任何设计文档提到过将其开发为任何产品的替代产品。资源?年龄本身不是一个因素。如果有选择,请选择最简单的实现来检查所有需求。
oligofren

1
就在两年前(2017年)我正在调试Node JS进程的堆转储,其中Socket.io代码在IIS进程中导致大量内存碎片,最终直接与Azure的Node团队交谈。总的复杂性不是免费的。如果您可以摆脱一个简单的20行脚本作为对服务器的依赖,同时仍然能够为10万个客户提供服务,那我就去做。我很喜欢WS的功能,但是在选择解决方案之前请先了解您的需求。
oligofren

16

Opera,Chrome,Safari支持SharedWorker内的SSE,Chrome,Safari支持SSE Firefox支持XMLHttpRequest readyState交互,因此我们可以为Firefox创建EventSource polyfil


8

Websocket VS SSE


Web套接字-这是一个协议,可通过单个TCP连接提供全双工通信通道。例如,服务器和浏览器之间的双向通信由于协议更加复杂,因此服务器和浏览器必须依靠websocket库,该库是socket.io

Example - Online chat application.

SSE(服务器发送事件)- 如果发生服务器发送事件,则仅从服务器到浏览器进行通信,浏览器无法将任何数据发送到服务器。这种通信主要在只需要显示更新的数据时使用,然后只要数据更新,服务器就会发送消息。例如,服务器与浏览器之间的单向通信。该协议不太复杂,因此无需依赖外部库JAVASCRIPT本身就提供了EventSource接收服务器发送的消息的接口。

Example - Online stock quotes or cricket score website.

4

需要注意的一件事:
我在使用websocket和公司防火墙时遇到了问题。(使用HTTPS有帮助,但并非总是如此。)

参见https://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software https://github.com/sockjs/sockjs-client/issues/94

认为服务器发送事件没有太多问题。但是我不知道。

就是说,WebSocket充满乐趣。我有一个使用websockets的小型网络游戏(通过Socket.IO)(http://minibman.com


1
我也有公司防火墙的问题。
oligofren

1
我发现服务器发送事件的一个问题是某些代理/防火墙可能会阻止它,因为它没有Content-Length标头
Drew LeSueur,


-3

最大连接限制不是http2 + sse的问题。

这是http 1上的问题


Http2允许将同一域上的多个请求视为流。这种技术称为多路复用。这样可以节省浏览器每个域的连接限制,这就是人们使用Http1进行域分片的原因。
user1948585 '18

1
HTTP / 2流的数量也受到限制,这可以防止服务器受到单个浏览器的轰炸,并迫使浏览器将其多路复用限制为有限数量的流-在我们的示例中,这与HTTP / 1.1连接相同。 。这将使您回到SSE连接限制。
Myst

我假设websocket连接也会消耗服务器资源。samsaffron.com/archive/2015/12/29/websockets-caution-required。能够根据自己的口袋配置尽可能多的功能总是很不错的。
user1948585 '18

SSE可能会在大多数服务器上消耗相似的资源(如果由于HTTP堆栈仍然存在且存在局限性,则可能会消耗更多资源)。
Myst

1
这个答案是正确的。使用HTTP / 2时,不再存在6个HTTP连接的限制。证明:codepen.io/dunglas/pen/yLYxdxK?editors=1010 使用HTTP / 2,服务器启动,客户端可以协商最大同时流数(默认为100)。
凯文Dunglas
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.