WebSockets和Server-Sent Events都能够向浏览器推送数据。它们似乎是竞争性技术。它们之间有什么区别?在何时会选择其中一种?
Websockets和SSE(服务器推送事件)都能够向浏览器推送数据,但它们不是竞争技术。
Websockets连接既可以向浏览器发送数据,也可以从浏览器接收数据。一个使用Websockets的好例子是聊天应用程序。
SSE连接只能向浏览器推送数据。在线股票报价或Twitter更新时间轴或信息流都是SSE可以受益的应用程序的好例子。
实际上,由于SSE可以做到的一切都可以用Websockets来完成,所以Websockets获得了更多的关注和爱,许多浏览器支持Websockets而不是SSE。
然而,对于某些类型的应用程序来说,这可能过度,而且后端使用SSE等协议可能更容易实现。
此外,SSE可以通过JavaScript在不支持它的旧版浏览器中进行填充。一些SSE polyfills的实现可以在Modernizr github页面上找到。
注意事项:
www.example1.com
,并在www.example2.com
上再打开6个SSE连接(感谢Phate)。HTML5Rocks提供了有关SSE的一些好信息。从该页面:
为什么你会选择使用服务器推送事件而不是WebSockets呢?这是一个好问题。
服务器推送事件一直被放在阴影之中的原因之一是,后来的API(如WebSockets)提供了更丰富的协议来执行双向全双工通信。拥有双向通道对于游戏、消息应用程序以及需要双向近实时更新的情况更具吸引力。然而,在某些情况下,数据不需要从客户端发送。您只需要来自某些服务器操作的更新。一些例子包括朋友的状态更新、股票行情、新闻提要或其他自动化数据推送机制(例如更新客户端Web SQL数据库或IndexedDB对象存储)。如果您需要向服务器发送数据,则XMLHttpRequest始终是您的好帮手。
服务器推送事件通过传统的HTTP发送。这意味着它们不需要特殊的协议或服务器实现才能正常工作。另一方面,WebSockets需要全双工连接和新的Web Socket服务器来处理协议。此外,服务器推送事件具有各种特性,设计上WebSockets缺乏,例如自动重新连接、事件ID和发送任意事件的能力。
服务器推送事件相对于Websockets的优势:
Websockets相对于服务器推送事件的优势:
服务器推送事件的理想用例:
服务器推送事件的注意事项:
根据caniuse.com的数据统计:
您可以使用仅客户端的polyfill将SSE协议扩展到许多其他浏览器上。但对于WebSockets协议来说这种情况不太可能发生。以下是一些EventSource polyfills:
如果您需要支持所有浏览器,请考虑使用像web-socket-js、SignalR或socket.io这样的库,它们支持多种传输方式,如WebSockets、SSE、Forever Frame和AJAX长轮询。这些通常还需要对服务器端进行修改。
可以从以下链接了解更多有关SSE协议的信息:
了解更多关于WebSockets的内容,请参考:
其他区别:
从历史上看,SSE存在一个严重的限制,即每个域名只能建立6个连接(当在多个浏览器标签中打开yourapp.com
时会出现问题),但这个问题在HTTP/2
中已经不再是一个问题。所有现代浏览器都支持HTTP/2
(全球用户占比97.16%),而在服务器端,HTTP/2+
在过去几年中也超过了HTTP/1
。
在选择SSE和WebSockets之间需要考虑各种因素:
curl
)。abc.com
使用1个SSE连接,但用户在7个以上的浏览器标签中打开了abc.com
,使用旧的HTTP/1
协议,用户将会遇到问题。 - at54321EventSource
接口。除了url
和withCredentials
标志之外,您无法设置其他任何内容。
因此,如果您的用例需要发送附加数据,您必须将其添加到URL查询字符串中,或者使用第三方实现,如fetch-event-source
。您还无法控制重试策略。EventSource将以固定间隔(由服务器定义)进行重试。 - MayThrowEventSource
存在一些限制,现在很多人都使用 fetch-event-source 作为一个更强大的替代方案。这一点非常重要,所以我更新了我的帖子。 - at54321WebSocket - 这是一种协议,它在单个TCP连接上提供全双工通信通道。
例如,在服务器和浏览器之间进行双向通信。由于该协议比较复杂,因此服务器和浏览器必须依赖websocket库,其中包括 socket.io
。
Example - Online chat application.
SSE(服务器推送事件) - 在服务器推送事件中,通信仅从服务器到浏览器进行,浏览器无法向服务器发送任何数据。这种通信主要用于只需要显示更新数据的情况下,服务器会在数据更新时发送消息。例如,服务器向浏览器的单向通信。由于该协议较为简单,因此无需依赖外部库,JavaScript本身提供EventSource
接口以接收服务器发送的消息。
Example - Online stock quotes or cricket score website.
Opera、Chrome和Safari支持SSE, Chrome和Safari支持SharedWorker内的SSE。 Firefox支持XMLHttpRequest的readyState交互,因此我们可以为Firefox制作EventSource polyfil。
需要注意的一点:
我曾与公司防火墙遇到过WebSockets相关的问题。(使用HTTPS有助于解决,但并非总是有效。)
详情请参见:https://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software, https://github.com/sockjs/sockjs-client/issues/94
我假设使用Server-Sent Events不会出现这样的问题,但我不确定。
话虽如此,WebSockets非常有趣。我有一个小型网络游戏,使用了WebSockets(通过Socket.IO实现)。(http://minibman.com)
它们在语义上不同。
WebSocket 具有“双向数据流”的本机语义含义。
而 SSE 具有“发布-订阅模式”或“请求-响应模式”的本机语义含义,尽管响应是一个数据流。
当然,您可以自己在 WebSocket 上实现一层“发布-订阅模式”或“请求-响应模式”的功能。
curl
打开到您的SSE服务器的请求。由于它只是基于HTTP的文本格式,所以很容易看出发生了什么。 - Sam