ChatGPT解决这个技术问题 Extra ChatGPT

socket.io 和 websockets 的区别

node.js中的socket.io和websockets有什么区别?它们都是服务器推送技术吗?我感觉到的唯一不同是,

socket.io 允许我通过指定事件名称来发送/发送消息。在 socket.io 的情况下,来自服务器的消息将到达所有客户端,但对于 websockets 中的相同,我被迫保留所有连接的数组并循环通过它以向所有客户端发送消息。

另外,我想知道为什么网络检查器(如 Chrome/firebug/fiddler)无法从服务器捕获这些消息(来自 socket.io/websocket)?

请澄清这一点。

关于网络检查器为何无法捕获流量:请参阅 How to view WS/WSS Websocket request content using Firebug or other?
@treaz 你不需要 Firebug 或其他任何东西。 Chrome 的开发工具在网络选项卡下显示 WS 连接。
也检查一下(不确定这是否是最新的) - educba.com/websocket-vs-socket-io
我认为默认的 socket.io 行为(在服务器端)不是将 msg 发送给所有客户端。我错了吗?我认为 socket.emit(event, data) 会将数据发送到特定的客户端而不是全部
请问有关于 Socket.io vs RSocket 的文档吗?

r
rsp

误解

关于 WebSocket 和 Socket.IO 的常见误解很少:

第一个误解是使用 Socket.IO 比使用 WebSocket 容易得多,但事实并非如此。请参阅下面的示例。第二个误解是浏览器没有广泛支持 WebSocket。有关更多信息,请参见下文。第三个误解是 Socket.IO 将连接降级为旧浏览器的后备。它实际上假设浏览器是旧的,并开始与服务器建立 AJAX 连接,稍后在交换一些流量后在支持 WebSocket 的浏览器上升级。详情见下文。

我的实验

我写了一个 npm 模块来演示 WebSocket 和 Socket.IO 之间的区别:

https://www.npmjs.com/package/websocket-vs-socket.io

https://github.com/rsp/node-websocket-vs-socket.io

这是一个服务器端和客户端代码的简单示例——客户端使用 WebSocket 或 Socket.IO 连接到服务器,服务器以 1s 的间隔发送三个消息,这些消息由客户端添加到 DOM。

服务器端

比较使用 WebSocket 和 Socket.IO 在 Express.js 应用程序中执行相同操作的服务器端示例:

WebSocket 服务器

使用 Express.js 的 WebSocket 服务器示例:

var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
  console.error('express connection');
  res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
  console.error('websocket connection');
  for (var t = 0; t < 3; t++)
    setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');

来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js

Socket.IO 服务器

使用 Express.js 的 Socket.IO 服务器示例:

var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
  console.error('express connection');
  res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
  console.error('socket.io connection');
  for (var t = 0; t < 3; t++)
    setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));
console.error('socket.io example');

来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.js

客户端

比较使用 WebSocket 和 Socket.IO 在浏览器中执行相同操作的客户端示例:

WebSocket 客户端

使用 vanilla JavaScript 的 WebSocket 客户端示例:

var l = document.getElementById('l');
var log = function (m) {
    var i = document.createElement('li');
    i.innerText = new Date().toISOString()+' '+m;
    l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });

来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html

Socket.IO 客户端

使用 vanilla JavaScript 的 Socket.IO 客户端示例:

var l = document.getElementById('l');
var log = function (m) {
    var i = document.createElement('li');
    i.innerText = new Date().toISOString()+' '+m;
    l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });

来源:https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.html

网络流量

要查看网络流量的差异,您可以run my test。这是我得到的结果:

WebSocket 结果

个请求,1.50 KB,0.05 秒

从这两个请求中:

HTML页面本身连接升级到WebSocket

(连接升级请求在开发人员工具上可见,并带有 101 Switching Protocols 响应。)

Socket.IO 结果

个请求,181.56 KB,0.25 秒

从这 6 个请求中:

HTML 页面本身 Socket.IO 的 JavaScript (180 KB) 第一次长轮询 AJAX 请求 第二次长轮询 AJAX 请求 第三次长轮询 AJAX 请求 连接升级到 WebSocket

截图

我在 localhost 上得到的 WebSocket 结果:

https://i.stack.imgur.com/e2yY5.png

我在 localhost 上得到的 Socket.IO 结果:

https://i.stack.imgur.com/RHymm.png

测试自己

快速开始:

# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io

在浏览器中打开 http://localhost:3001/,使用 Shift+Ctrl+I 打开开发者工具,打开网络选项卡并使用 Ctrl+R 重新加载页面以查看 WebSocket 版本的网络流量。

在浏览器中打开 http://localhost:3002/,使用 Shift+Ctrl+I 打开开发者工具,打开网络选项卡并使用 Ctrl+R 重新加载页面以查看 Socket.IO 版本的网络流量。

要卸载:

# Uninstall:
npm rm -g websocket-vs-socket.io

浏览器兼容性

截至 2016 年 6 月,WebSocket 可在除 Opera Mini 之外的所有设备上运行,包括高于 9 的 IE。

这是截至 2016 年 6 月 Can I Use 上 WebSocket 的浏览器兼容性:

https://i.stack.imgur.com/igTKM.png

有关最新信息,请参阅 http://caniuse.com/websockets


所以基本上你要说的是,websocket 比 socket.io 好?
@JackMoscovi 我不会说 WebSocket 一定更好。这一切都取决于要求。 WebSocket 的优点是它是一个 Web 标准(最初在 W3C 和 whatwg,现在在 IETF,5 年前有一个 RFC 发布),它非常轻量级,因为它是浏览器原生支持的,但浏览器支持良好的同时是不是通用的。 Socket.IO 支持更多的浏览器和更多的功能,但也带来了一些开销。有时一个更好,有时另一个。这就像在 querySelectorAll 和 jQuery 之间进行选择 - 答案并不总是相同的
很好的答案在这里!在我看来,socket.io 在许多情况下不再是必需的......也请参阅这篇很棒的文章! medium.com/@ivanderbyl/…
很好的对比。然而,值得注意的是 Socket.io 增加了房间名称间距、大量连接细节、大量日志记录细节,并且有大量 Socket.IO 与 Angular、Vue、React 等的集成库。最重要的是,您可以禁用 Ajax 长轮询并直接通过 WebSocket 连接,就像原始 WebSocket 连接一样。这样一来,除了 180kb 库之外,您都可以平等地获得所有内容。除非您只需要最低限度,否则直接使用 WebSocket 会很痛苦。放置房间和访问社区 IP 对企业来说是一项艰巨的任务。
SocketIO 实际上比 websockets 更容易。 OP 编写的代码利用了一些 SocketIO 的特性,他没有用 Websockets 的代码复制这些特性,例如房间和潜艇。 SocketIO 为您提供协议和订阅服务。而 Websocket 则迫使您制定自己的架构和协议。这意味着您必须使用 Websockets 编写 10 倍以上的代码,并且必须花费 x100 倍的时间来设计架构并调试您犯的每一个错误(相信我,这就是我在这里重新调查我的决定的原因)。 SocketIO 不仅支持旧版浏览器,它也更容易
S
StackedQ

它的优点是它简化了 WebSockets 的使用,正如您在 #2 中描述的那样,并且可能更重要的是,它提供了在浏览器或服务器不支持 WebSockets 的情况下对其他协议的故障转移。我会避免直接使用 WebSockets,除非您非常熟悉它们不工作的环境并且您能够解决这些限制。

这是一本关于 WebSockets 和 Socket.IO 的好书。

http://davidwalsh.name/websocket


Socket.IO 不是建立在 WebSockets 之上的,它只是在可用时使用这种技术。
语义差异,我在答案的其余部分解释了这一点,但我已经更新了答案以反映这一点。
@moka,从你的话中我可以得出以下结论是错误的吗? Socket.IO 实际上不仅仅是 WebSockets 之上的一层。
@PulakKantiBhattacharyya 您能否具体说明您指的是哪个声明? Socket.IO 不仅仅是 WebSockets 之上的一层,它具有不同的语义(用名称标记消息),并且可以对不同的协议进行故障转移,还有心跳机制。更重要的是,将 ID 附加到服务器端的客户端等等。所以它不仅仅是一个包装器,它是一个功能齐全的库。事实上,近年来它并没有得到很好的支持,所以我建议使用 SockJS,它比 Socket.IO 更好、维护得更好。
@moka 一个月前我会同意你的。 Socket.io 1.0 现已发布并正在更新。
E
Eksapsy

tl;博士;

比较它们就像比较餐厅的食物(有时可能很贵,也许不是 100% 你想要它)与自制食物,你必须自己收集和种植每种成分。

也许如果你只是想吃一个苹果,后者更好。但是如果你想要一些复杂的东西并且你一个人,那真的不值得自己做饭和制作所有的食材。

我已经与这两个工作过。这是我的经验。

套接字IO

有自动连接

有命名空间

有房间

有订阅服务

具有预先设计的通信协议(谈论订阅,取消订阅或向特定房间发送消息的协议,您必须自己在 websockets 中设计它们)

具有良好的日志记录支持

已与redis等服务集成

在不支持 WS 的情况下具有后备功能(不过,这种情况越来越少见)

这是一个图书馆。这意味着,它实际上在各个方面都在帮助您的事业。 Websockets 是一个协议,而不是一个库,SocketIO 无论如何都使用它。

整个架构由不是您的人支持和设计,因此您不必花时间设计和实现上述任何内容,但您可以直接编写业务规则。

有一个社区,因为它是一个库(你不能有一个用于 HTTP 或 Websockets 的社区:P 它们只是标准/协议)

网络套接字

你拥有绝对的控制权,这取决于你是谁,这可能非常好或非常糟糕

它很轻(记住,它是一个协议,而不是一个库)

您设计自己的架构和协议

没有自动连接,如果需要,您可以自己实现

没有订阅服务,你自己设计

没有日志记录,你实现它

没有后备支持

没有房间或命名空间。如果你想要这样的概念,你自己实现它们

不支持任何东西,你将是实现一切的人

您首先必须专注于技术部分并设计进出您的 Websocket 的所有内容

你必须先调试你的设计,这将花费你很长时间

显然,你可以看到我偏向于 SocketIO。我很想这么说,但我真的不是。

我真的在努力不使用 SocketIO。我不想用它。我喜欢设计自己的东西并自己解决自己的问题。

但是如果你想拥有一个业务而不仅仅是一个 1000 行的项目,并且你要选择 Websockets,你将不得不自己实现每一件事。你必须调试一切。您必须制作自己的订阅服务。您自己的协议。你自己的一切。你必须确保一切都非常复杂。而且你会在这个过程中犯很多错误。您将花费大量时间设计和调试所有内容。我做到了,现在仍然这样做。我正在使用 websockets,我在这里的原因是因为对于一个试图为他的初创公司解决业务规则而不是处理 Websocket 设计术语的人来说,它们是难以忍受的。

如果您是单人军队或试图实现复杂功能的小团队,那么为大型应用程序选择 Websocket 并不是一个简单的选择。我在 Websockets 中编写的代码比过去使用 SocketIO 编写的代码还要多,比使用 SocketIO 编写的代码简单十倍。

我要说的是……如果您想要成品和设计,请选择 SocketIO。 (除非您想要功能非常简单的东西)


J
Jim Buck

我将提供一个反对使用 socket.io 的论点。

我认为仅仅因为它具有后备功能而使用 socket.io 并不是一个好主意。让 IE8 RIP。

过去有很多新版本的 NodeJS 破坏了 socket.io 的情况。您可以查看这些列表以获取示例... https://github.com/socketio/socket.io/issues?q=install+error

如果你要开发一个 Android 应用程序或需要与现有应用程序一起工作的东西,你可能马上就可以使用 WS,socket.io 可能会给你带来一些麻烦......

此外,Node.JS 的 WS 模块使用起来非常简单。


D
Dev Agrawal

使用 Socket.IO 基本上就像使用 jQuery - 你想支持旧版浏览器,你需要编写更少的代码,并且库将提供回退。 Socket.io 使用 websockets 技术(如果可用),如果不可用,则检查可用的最佳通信类型并使用它。


据我所知,我认为这是一个不好的例子,因为 jQuery 不支持旧版浏览器。这给新手的印象是现在应该使用 jQuery。如果您使用最新的 ECMA,则可以使用 babel。 :D 请原谅我的吹毛求疵,我只是看到新手一直无缘无故地使用 jQuery,因为他们在 javascript 之前学习 jquery,我只是想为减少这种不良实践现象做出贡献。
很好地支持浏览器的不一致是 jQuery 的最初目的。如果您查看我的答案上的日期,您会明白的。当然,它并没有很好地老化,因为现在浏览器的不一致已经不存在了。
K
Ken Lin

https://socket.io/docs/#What-Socket-IO-is-not(我强调

什么 Socket.IO 不是 Socket.IO 不是 WebSocket 实现。尽管 Socket.IO 确实尽可能使用 WebSocket 作为传输,但它会为每个数据包添加一些元数据:数据包类型、命名空间和需要消息确认时的数据包 ID。这就是为什么 WebSocket 客户端将无法成功连接到 Socket.IO 服务器,而 Socket.IO 客户端也将无法连接到 WebSocket 服务器。请在此处查看协议规范。 // 警告:客户端将无法连接!常量客户端 = io('ws://echo.websocket.org');


M
Maxime Lafarie

即使现代浏览器现在支持 WebSockets,我认为没有必要抛弃 SocketIO,它仍然在当今的任何项目中占有一席之地。这很容易理解,而且就个人而言,我通过 SocketIO 了解了 WebSockets 的工作原理。

如本主题所述,有大量用于 Angular、React 等的集成库以及用于 TypeScript 和其他编程语言的定义类型。

我要补充的关于 Socket.io 和 WebSockets 之间差异的另一点是,使用 Socket.io 进行集群并不是什么大问题。 Socket.io 提供 Adapters 可用于将其与 Redis 链接以增强可扩展性。例如,您有 ioredissocket.io-redis

是的,我知道,SocketCluster 存在,但这是题外话。


Q
Qiulang

我想在 2021 年再提供一个答案。socket.io 自 2020 年 9 月以来再次得到积极维护。在 2019 年至 2020 年 8 月(近 2 年)期间,基本上没有任何活动,我原以为该项目可能已经死了。

Socket.io 也发表了一篇文章叫Why Socket.IO in 2020?,除了回退到 HTTP 长轮询,我认为这 2 个特性是 socket.io 提供而 websocket 缺乏的

自动重新连接

一种向给定客户端(房间/命名空间)广播数据的方法

我发现 socket.io 的另一个方便的功能是用于 ws 服务器开发,尤其是我使用 docker 进行服务器部署。因为我总是启动超过 1 个服务器实例,所以跨 ws 服务器通信是必须的,socket.io 为它提供了 https://socket.io/docs/v4/redis-adapter/

使用 redis-adapter,将服务器进程扩展到多个节点很容易,而 ws 服务器的负载平衡很难。点击此处https://socket.io/docs/v4/using-multiple-nodes/了解更多信息。


N
Nitin .

Socket.IO 使用 WebSocket,当 WebSocket 不可用时,使用回退算法进行实时连接。