介绍
Socket.IO 是什么
¥What Socket.IO is
Socket.IO 是一个库,可在客户端和服务器之间实现低延迟、双向和基于事件的通信。
¥Socket.IO is a library that enables low-latency, bidirectional and event-based communication between a client and a server.
Socket.IO 连接可以通过不同的底层传输建立:
¥The Socket.IO connection can be established with different low-level transports:
HTTP 长轮询
¥HTTP long-polling
Socket.IO 将自动选择最佳可用选项,具体取决于:
¥Socket.IO will automatically pick the best available option, depending on:
网络(某些网络阻止 WebSocket 和/或 WebTransport 连接)
¥the network (some networks block WebSocket and/or WebTransport connections)
你可以在 "工作原理" 节 中找到更多详细信息。
¥You can find more detail about that in the "How it works" section.
服务器实现
¥Server implementations
语言 | 网站 |
---|---|
JavaScript (Node.js) | * 安装步骤 - API - 源代码 |
JavaScript(Deno) | https://github.com/socketio/socket.io-deno |
Java | https://github.com/mrniko/netty-socketio |
Java | https://github.com/trinopoty/socket.io-server-java |
Python | https://github.com/miguelgrinberg/python-socketio |
Golang | https://github.com/googollee/go-socket.io |
Rust | https://github.com/Totodore/socketioxide |
客户端实现
¥Client implementations
Socket.IO 不是什么
¥What Socket.IO is not
Socket.IO 不是 WebSocket 实现。
¥Socket.IO is NOT a WebSocket implementation.
尽管 Socket.IO 确实在可能的情况下使用 WebSocket 进行传输,但它会向每个数据包添加额外的元数据。这就是为什么 WebSocket 客户端将无法成功连接到 Socket.IO 服务器,并且 Socket.IO 客户端也将无法连接到普通 WebSocket 服务器。
¥Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a plain WebSocket server either.
// WARNING: the client will NOT be able to connect!
const socket = io("ws://echo.websocket.org");
如果你正在寻找普通的 WebSocket 服务器,请查看 ws 或 µWebSockets.js。
¥If you are looking for a plain WebSocket server, please take a look at ws or µWebSockets.js.
还有 讨论 用于在 Node.js 核心中包含 WebSocket 服务器。
¥There are also discussions for including a WebSocket server in the Node.js core.
在客户端,你可能对 robust-websocket 包感兴趣。
¥On the client-side, you might be interested in the robust-websocket package.
Socket.IO 不适合在移动应用的后台服务中使用。
¥Socket.IO is not meant to be used in a background service for mobile applications.
Socket.IO 库与服务器保持开放的 TCP 连接,这可能会导致用户消耗大量电池。对于此用例,请使用专用消息传递平台(例如 FCM)。
¥The Socket.IO library keeps an open TCP connection to the server, which may result in a high battery drain for your users. Please use a dedicated messaging platform like FCM for this use case.
特性
¥Features
以下是 Socket.IO 通过普通 WebSocket 提供的功能:
¥Here are the features provided by Socket.IO over plain WebSockets:
HTTP 长轮询回退
¥HTTP long-polling fallback
如果无法建立 WebSocket 连接,连接将回退到 HTTP 长轮询。
¥The connection will fall back to HTTP long-polling in case the WebSocket connection cannot be established.
此功能是十多年前创建 Socket.IO 项目时人们使用 Socket.IO 的第一大原因(!),因为浏览器对 WebSockets 的支持仍处于起步阶段。
¥This feature was the #1 reason people used Socket.IO when the project was created more than ten years ago (!), as the browser support for WebSockets was still in its infancy.
即使大多数浏览器现在都支持 WebSocket(超过 97%),它仍然是一个很棒的功能,因为我们仍然收到用户的报告,称他们无法建立 WebSocket 连接,因为他们位于某些配置错误的代理后面。
¥Even if most browsers now support WebSockets (more than 97%), it is still a great feature as we still receive reports from users that cannot establish a WebSocket connection because they are behind some misconfigured proxy.
自动重连
¥Automatic reconnection
在某些特定条件下,服务器和客户端之间的 WebSocket 连接可能会中断,而双方都不知道链接的中断状态。
¥Under some particular conditions, the WebSocket connection between the server and the client can be interrupted with both sides being unaware of the broken state of the link.
这就是 Socket.IO 包含心跳机制的原因,该机制会定期检查连接的状态。
¥That's why Socket.IO includes a heartbeat mechanism, which periodically checks the status of the connection.
当客户端最终断开连接时,它会自动以指数回退延迟重新连接,以免服务器不堪重负。
¥And when the client eventually gets disconnected, it automatically reconnects with an exponential back-off delay, in order not to overwhelm the server.
数据包缓冲
¥Packet buffering
当客户端断开连接时,数据包会自动缓存,并在重新连接时发送。
¥The packets are automatically buffered when the client is disconnected, and will be sent upon reconnection.
更多信息在 此处。
¥More information here.
回执
¥Acknowledgements
Socket.IO 提供了一种发送事件和接收响应的便捷方法:
¥Socket.IO provides a convenient way to send an event and receive a response:
发送者
¥Sender
socket.emit("hello", "world", (response) => {
console.log(response); // "got it"
});
接收者
¥Receiver
socket.on("hello", (arg, callback) => {
console.log(arg); // "world"
callback("got it");
});
你还可以添加超时:
¥You can also add a timeout:
socket.timeout(5000).emit("hello", "world", (err, response) => {
if (err) {
// the other side did not acknowledge the event in the given delay
} else {
console.log(response); // "got it"
}
});
广播
¥Broadcasting
在服务器端,你可以向 所有连接的客户端 或 给一部分客户端 发送事件:
¥On the server-side, you can send an event to all connected clients or to a subset of clients:
// to all connected clients
io.emit("hello");
// to all connected clients in the "news" room
io.to("news").emit("hello");
这在 扩展到多个节点 时也有效。
¥This also works when scaling to multiple nodes.
多路复用
¥Multiplexing
命名空间允许你通过单个共享连接拆分应用的逻辑。例如,如果你想要创建只有授权用户才能加入的 "管理" 通道,这可能会很有用。
¥Namespaces allow you to split the logic of your application over a single shared connection. This can be useful for example if you want to create an "admin" channel that only authorized users can join.
io.on("connection", (socket) => {
// classic users
});
io.of("/admin").on("connection", (socket) => {
// admin users
});
此处 有更多信息。
¥More on that here.
常见问题
¥Common questions
今天还需要 Socket.IO 吗?
¥Is Socket.IO still needed today?
这是一个公平的问题,因为 WebSockets 现在 几乎到处 支持。
¥That's a fair question, since WebSockets are supported almost everywhere now.
话虽如此,我们相信,如果你在应用中使用普通的 WebSocket,你最终将需要实现 Socket.IO 中已包含(并经过实际测试)的大部分功能,例如 重新连接、acknowledgements 或 广播。
¥That being said, we believe that, if you use plain WebSockets for your application, you will eventually need to implement most of the features that are already included (and battle-tested) in Socket.IO, like reconnection, acknowledgements or broadcasting.
Socket.IO 协议的开销是多少?
¥What is the overhead of the Socket.IO protocol?
socket.emit("hello", "world")
将作为包含 42["hello","world"]
的单个 WebSocket 帧发送,其中:
¥socket.emit("hello", "world")
will be sent as a single WebSocket frame containing 42["hello","world"]
with:
4
是 Engine.IO "message" 数据包类型¥
4
being Engine.IO "message" packet type2
是 Socket.IO "message" 数据包类型¥
2
being Socket.IO "message" packet type["hello","world"]
是参数数组的JSON.stringify()
版本¥
["hello","world"]
being theJSON.stringify()
-ed version of the arguments array
因此,每个消息需要一些额外的字节,可以通过使用 自定义解析器 进一步减少。
¥So, a few additional bytes for each message, which can be further reduced by the usage of a custom parser.
你可以找到 Socket.IO 协议 此处 的详细信息。
¥You can find the details of the Socket.IO protocol here.
有些东西不能正常工作,请帮忙?
¥Something does not work properly, please help?
请检查我们的 故障排除指南。
¥Please check our Troubleshooting guide.
下一步
¥Next steps