朋友们,美好的一天!Web套接字和Socket.IO可能是两种最常见的实时通信方式(以下称为实时通信)。但是它们有何不同?在构建用于实时通信的应用程序时,有时需要选择一种用于在客户端和服务器之间交换数据的工具。Web套接字和Socket.IO是现代Web上最流行的实时通信方式。选择哪一个?这些技术之间有什么区别?让我们找出答案。网络插座
说到网络套接字,我们指的是网络通信协议,它表示通过简单TCP连接的全双工通信通道。简而言之,这项技术使您能够以最小的成本在客户端和服务器之间建立通信,从而使您能够创建利用实时通信所有优点的应用程序。例如,假设您正在创建聊天:您需要尽快接收和发送数据,对吗?Web套接字就可以了!您可以打开一个TCP连接,并在需要时保持打开状态。Web套接字于2010年出现在Google Chrome 4中,第一个RFC(6455)于2011年发布。在以下情况下使用Web套接字:- 聊天室
- 多人游戏
- 协同编辑
- 社会(新闻)提要
- 基于位置的应用
等等套接字
Socket.IO是一个基于Web套接字...和其他技术的JavaScript库(写在顶部)。如果可用,则使用Web套接字;如果不可用,则使用Flash Socket,AJAX Long Polling,AJAX Multipart Stream等技术。一个简单的类比是Fetch API和Axios的比较。Web套接字和Socket.IO之间的区别
Socket.IO的主要优点如下:- -, Socket.IO . , . . -, .
- - . Socket.IO .
- , Socket.IO () .
- Socket.IO .
- Socket.IO .
似乎Socket.IO是实时通信的最佳工具。但是,在某些情况下,最好使用Web套接字。首先,所有现代浏览器都支持Web套接字。因此,您很少需要Socket.IO提供的其他技术的支持。如果我们谈论网络流量,则Web套接字仅发送两个请求:这使您可以连接到服务器。Socket.IO呢?- 获取以获取HTML页面
- Socket.IO客户端库(207kb)
- 三个长轮询Ajax请求
- 升级用于连接Web套接字
在JS的世界中,207kb非常多。多么不合理地使用网络流量!在npm中,有一个软件包“ websocket-vs-socket.io”,可让您比较以下技术的网络流量:Web套接字网络流量:

Socket.IO网络流量:
区别很明显!编写代码
简单的Web套接字服务器
在Node.js上的程序中,我们将创建一个在端口3001上运行的服务器。每次客户端连接时,我们都会为其分配一个唯一的ID。向客户发送消息时,我们将通知他成功:[<client-id>]:<message>const WebSocket = require('ws')
const UUID = require('uuid')
const wss = new WebSocket.Server({ port: 3001 })
wss.on('connection', ws => {
ws.id = UUID()
ws.on('message', message => {
ws.send(`[${ws.id}]: ${message}`)
})
})
精细!但是,如果我们想向每个连接的客户端发送消息怎么办?Web套接字默认情况下不支持邮件。可以如下实现:const WebSocket = require("ws")
const UUID = require("uuid")
const wss = new WebSocket.Server({ port: 3001 })
function broadcast(clientId, message) {
wss.clients.forEach(client => {
if(client.readyState === WebSocket.OPEN) {
client.send(`[${clientId}]: ${message}`)
}
})
}
wss.on('conection', ws => {
ws.id = UUID()
ws.on('message', message => broadcast(ws.id, message))
})
简单轻松!如您所见,WebSocket.Server会保留每个连接的客户端的记录,因此我们可以迭代并向每个人发送消息。您可以在计算机(MacOS)或浏览器(Chrome)中测试代码。Socket.IO上的简单服务器
这并不困难。Socket.IO可以使它更容易吗?我们如何在Socket.IO上写入同一服务器?const io = require('socket.io')
const server = io.listen(3002)
server.on('connection', socket => {
socket.on('message', message => {
socket.emit(`[${socket.id}]: ${message}`)
socket.broadcast.emit(`[${socket.id}]: ${message}`)
})
})
代码几乎短了一半!如您所见,广播方法不会将通知发送给发件人,因此我们被迫手动执行此操作。有一个问题:无法在常规的Web套接字客户端上测试代码。如前所述,这是由于Socket.IO不使用纯Web套接字,而是使用许多技术来支持所有可能的客户端的事实。那么我们如何测试其性能呢?
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2.3.0/dist/socket.io.slim.js"></script>
<script>
ioClient = io.connect('http://localhost:3002')
ioClient.on('connect', socket => {
ioClient.send('hello world')
ioClient.on('message', msg => console.log(msg))
})
</script>
您必须使用特殊的客户端。在上面的示例中,我们从CDN加载它。该客户端允许我们在浏览器中进行快速(脏)测试。如您所见,我们的示例并没有太大不同。但是,如果我们谈论兼容性,则应记住Socket.IO使用其自己的库,不能将其用于与Web开发无关的目的。同时,Web套接字可用于解决各种任务,例如P2P通信,服务器之间的实时数据交换等。在笔记上
水平缩放。假设您的聊天越来越流行,您需要添加其他服务器和负载平衡器来处理请求。好吧,如果您打开到“服务器1”的连接,那么平衡器会将您切换到“服务器2”,您将收到错误:“ WebSocket握手期间错误:意外的响应代码:400”。 Socket.IO通过使用cookie(或通过基于源地址的路由连接)解决了此问题,并且Web套接字没有这种机制。性能。如前所述,Socket.IO在Web套接字的传输层之上提供了几个抽象层。另外,此处使用将数据打包为JSON格式,因此不可能将二进制数据发送到服务器(反之亦然)。如果需要这种功能,则必须“构想”库代码以确保所需的行为。使用Web套接字不会出现此类问题。那么该选择什么呢?
你决定。Socket.IO使生活更轻松,您无需担心与负载平衡,断开连接或发送消息有关的问题……但是您是否需要这种功能?Socket.IO客户端库的重量超过React,Redux和React-Redux软件包的总和。确定要限制自己使用网络套接字吗?要记住的另一件事是,在服务器端使用Socket.IO时,大多数代码将以该库提供的抽象形式编写。如果您需要用Go,Elixir,Java或其他编程语言重写Node.js微服务,则必须重写几乎所有逻辑。例如,要将消息发送到Socket.IO,则使用“广播”方法(在Web套接字上手动实现),因此在重构时,您将必须了解该方法的工作方式。在这种情况下,应该首选Web套接字,因为它们更容易适应。感谢您的关注。