socket.io和websockets之间的区别


458

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

  1. socket.io允许我通过指定事件名称来发送/发送消息。

  2. 对于socket.io,来自服务器的消息将到达所有客户端,但对于websockets中的消息,我被迫保留所有连接的数组并循环遍历,以将消息发送给所有客户端。

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

请澄清一下。


6
关于为何Web检查员无法捕获流量:请参阅如何使用Firebug或其他方法查看WS / WSS Websocket请求内容?
treaz 2012年

1
@treaz您不需要Firebug或其他任何东西。Chrome的devtools在“网络”标签下显示WS连接。

也请检查此内容(不确定是否最新)-educba.com/websocket-vs-socket-io
Manohar Reddy Poreddy

Answers:


325

它的优点是,它简化了如#2中所述的WebSockets的使用,并且可能更重要的是,如果浏览器或服务器不支持WebSockets,它可以将故障转移到其他协议。我将避免直接使用WebSocket,除非您非常熟悉Web套接字在什么环境下不起作用,并且您能够解决这些限制。

这对WebSockets和Socket.IO都是不错的阅读。

http://davidwalsh.name/websocket


63
Socket.IO并非基于WebSockets构建,而是在可用时才使用该技术。
moka

24
语义上的差异,我在答案的其余部分中对此进行了解释,但是我已经更新了答案以反映这一点。
Timothy Strimple

1
@moka,从您的话中我可以得出结论,以下说法是错误的?Socket.IO实际上不仅仅是WebSockets上的一层。
Pulak Kanti Bhattacharyya 2014年

3
@PulakKantiBhattacharyya您能否指定您确切指的是哪条陈述?Socket.IO不仅是WebSockets之上的一层,它还具有不同的语义(使用名称标记消息),并且可以将故障转移到不同的协议,还具有心跳机制。除此之外,还可以在服务器端将ID附加到客户端。因此,它不仅是包装器,还是功能齐全的库。实际上,近年来它没有得到很好的支持,所以我建议使用SockJS,它比Socket.IO更好,并且维护性更高。
moka,2014年

4
@moka一个月前,我会同意你的。Socket.io 1.0现已发布,正在获取更新。
蒂莫西·斯特劳夫

536

误解

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

  1. 第一个误解是,使用Socket.IO比使用WebSocket容易得多,而事实并非如此。请参阅下面的示例。

  2. 第二个误解是浏览器未广泛支持WebSocket。请参阅下面的更多信息。

  3. 第三个误解是Socket.IO将连接降级作为旧版浏览器的后备。实际上,它假定浏览器是旧的,并开始与服务器建立AJAX连接,然后在交换某些流量之后,在支持WebSocket的浏览器上对其进行升级。有关详情,请参见下文。

我的实验

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

这是服务器端和客户端代码的简单示例-客户端使用WebSocket或Socket.IO连接到服务器,服务器以1秒的间隔发送三个消息,这些消息由客户端添加到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客户端

使用普通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客户端

使用原始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

网络流量

要查看网络流量的差异,可以运行我的测试。这是我得到的结果:

WebSocket结果

2个请求,1.50 KB,0.05 s

从这2个请求中:

  1. HTML页面本身
  2. 连接升级到WebSocket

(连接升级请求在开发人员工具上显示为101交换协议响应。)

Socket.IO结果

6个请求,181.56 KB,0.25 s

从这6个请求中:

  1. HTML页面本身
  2. Socket.IO的JavaScript(180 KB)
  3. 第一个长期轮询AJAX请求
  4. 第二次长时间轮询AJAX请求
  5. 第三次长时间轮询AJAX请求
  6. 连接升级到WebSocket

屏幕截图

我在本地主机上得到的WebSocket结果:

WebSocket结果-websocket-vs-socket.io模块

我在本地主机上获得的Socket.IO结果:

Socket.IO结果-websocket-vs-socket.io模块

测试自己

快速开始:

# 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 Opera以外的所有平台上运行,包括高于9的IE。

自2016年6月起,这是WebSocket在“我可以使用”上的浏览器兼容性:

在此处输入图片说明

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


23
因此,基本上您说的是,websocket比socket.io更好?
杰克·莫斯科维

42
@JackMoscovi我不会说WebSocket一定更好。这完全取决于要求。WebSocket的优点是它是一个Web标准(首先是在W3C和whatwg下,现在在IETF下,并且在5年前发布了RFC),它非常轻巧,因为它是浏览器的本机支持,但是很好的浏览器支持是不普遍。Socket.IO支持更多的浏览器并具有更多的功能,但同时也带来一些开销。有时一个更好,有时另一个更好。就像在querySelectorAll和jQuery之间进行选择-答案并不总是相同
rsp

20
好答案在这里!在我看来,在许多情况下,socket.io不再是必需的……也请参阅这篇出色的文章!medium.com/@ivanderbyl/…–
Alvaro

4
@rsp我认为这些示例在功能上并不等效吗?套接字io处理中断时自动重新连接之类的事情(发生在移动设备上),我认为围绕这​​些问题为您处理安全问题?您的普通WS示例虽然在功能上等效,但没有这些属性。
mindplay.dk

28
比较好。但是,值得注意的是,Socket.io添加了房间名称间距,大量的连接详细信息,大量的日志记录详细信息,并且为Socket.IO提供了许多集成库,其中包含Angular,Vue,React等。最重要的是,您可以禁用Ajax长轮询并直接通过WebSocket进行连接,就像原始WebSocket连接一样。这样,您可以获得除180kb库之外的所有内容。除非您只需要最低限度的知识,否则直接使用WebSocket会很痛苦。放弃房间和访问社区IP对于企业来说是一项艰巨的任务。
尼克·斯蒂尔

30

我将提供一个反对使用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模块非常易于使用。


您建议我们使用什么与mysql进行交互-> express.js / fastify.js或node.js直接...来构建android和ios聊天应用程序
DragonFire

25

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


3

即使现代浏览器现在支持WebSockets,我也认为没有必要丢弃SocketIO,并且它在当今的任何项目中都占有一席之地。这很容易理解,而且我个人通过SocketIO学会了WebSockets的工作方式。

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

我要添加到Socket.io和WebSockets之间的区别的另一点是,使用Socket.io进行群集并不是什么大问题。Socket.io提供了可用于将其与Redis链接以增强可伸缩性的适配器。例如,您有ioredissocket.io-redis

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


2

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


0

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

什么不是Socket.IO

Socket.IO 不是 WebSocket实现。尽管Socket.IO确实确实在可能的情况下使用WebSocket进行传输,但它在每个数据包中添加了一些元数据:当需要消息确认时,数据包类型,名称空间和数据包ID。因此,WebSocket客户端将无法成功连接到Socket.IO服务器,而Socket.IO客户端也将无法连接到WebSocket服务器。请在此处查看协议规范。

// WARNING: the client will NOT be able to connect!
const client = io('ws://echo.websocket.org');
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.