Skip to main content
Version: 4.x

Socket 实例(客户端)

Socket 是与服务器交互的基本类。它继承了 Node.js EventEmitter 的大部分方法,如 emitononceoff

¥A Socket is the fundamental class for interacting with the server. It inherits most of the methods of the Node.js EventEmitter, like emit, on, once or off.

Bidirectional communication between server and clientBidirectional communication between server and client

除了 emitting 事件之外,Socket 实例还有一些可能在你的应用中使用的属性:

¥Besides emitting and listening to events, the Socket instance has a few attributes that may be of use in your application:

Socket#id

每个新连接都会分配一个随机的 20 个字符标识符。

¥Each new connection is assigned a random 20-characters identifier.

该标识符与服务器端的值同步。

¥This identifier is synced with the value on the server-side.

// server-side
io.on("connection", (socket) => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});

// client-side
socket.on("connect", () => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});

socket.on("disconnect", () => {
console.log(socket.id); // undefined
});
caution

请注意,除非启用 连接状态恢复,否则 id 属性是一个临时 ID,不适合在你的应用中使用(或仅用于调试目的),因为:

¥Please note that, unless connection state recovery is enabled, the id attribute is an ephemeral ID that is not meant to be used in your application (or only for debugging purposes) because:

  • 每次重新连接后都会重新生成此 ID(例如当 WebSocket 连接被切断时,或者当用户刷新页面时)

    ¥this ID is regenerated after each reconnection (for example when the WebSocket connection is severed, or when the user refreshes the page)

  • 两个不同的浏览器选项卡将有两个不同的 ID

    ¥two different browser tabs will have two different IDs

  • 服务器上没有为给定 ID 存储消息队列(即如果客户端断开连接,从服务器发送到该 ID 的消息就会丢失)

    ¥there is no message queue stored for a given ID on the server (i.e. if the client is disconnected, the messages sent from the server to this ID are lost)

请改用常规会话 ID(在 cookie 中发送,或存储在 localStorage 中并在 auth 有效负载中发送)。

¥Please use a regular session ID instead (either sent in a cookie, or stored in the localStorage and sent in the auth payload).

也可以看看:

¥See also:

Socket#connected

该属性描述套接字当前是否连接到服务器。

¥This attribute describes whether the socket is currently connected to the server.

socket.on("connect", () => {
console.log(socket.connected); // true
});

socket.on("disconnect", () => {
console.log(socket.connected); // false
});

Socket#io

对底层 管理者 的引用。

¥A reference to the underlying Manager.

socket.on("connect", () => {
const engine = socket.io.engine;
console.log(engine.transport.name); // in most cases, prints "polling"

engine.once("upgrade", () => {
// called when the transport is upgraded (i.e. from HTTP long-polling to WebSocket)
console.log(engine.transport.name); // in most cases, prints "websocket"
});

engine.on("packet", ({ type, data }) => {
// called for each packet received
});

engine.on("packetCreate", ({ type, data }) => {
// called for each packet sent
});

engine.on("drain", () => {
// called when the write buffer is drained
});

engine.on("close", (reason) => {
// called when the underlying connection is closed
});
});

生命周期

¥Lifecycle

Lifecycle diagramLifecycle diagram

事件

¥Events

Socket 实例触发三个特殊事件:

¥The Socket instance emits three special events:

tip

从 Socket.IO v3 开始,Socket 实例不再触发任何与重新连接逻辑相关的事件。你可以直接监听 Manager 实例上的事件:

¥Since Socket.IO v3, the Socket instance does not emit any event related to the reconnection logic anymore. You can listen to the events on the Manager instance directly:

socket.io.on("reconnect_attempt", () => {
// ...
});

socket.io.on("reconnect", () => {
// ...
});

更多信息可以在 迁移指南 中找到。

¥More information can be found in the migration guide.

connect

该事件由 Socket 实例在连接和重新连接时触发。

¥This event is fired by the Socket instance upon connection and reconnection.

socket.on("connect", () => {
// ...
});
caution

事件处理程序不应在 connect 处理程序本身中注册,因为每次套接字实例重新连接时都会注册一个新的处理程序:

¥Event handlers shouldn't be registered in the connect handler itself, as a new handler will be registered every time the socket instance reconnects:

不好:警告:

¥BAD ⚠️

socket.on("connect", () => {
socket.on("data", () => { /* ... */ });
});

GOOD 👍

socket.on("connect", () => {
// ...
});

socket.on("data", () => { /* ... */ });

connect_error

连接失败时会触发此事件。

¥This event is fired upon connection failure.

原因自动重连?
无法建立底层连接(暂时失败):白色复选标记:是的
连接在 中间件函数 中被服务器拒绝:X:不

socket.active 属性表示 socket 是否会在小 随机延迟 后自动尝试重新连接:

¥The socket.active attribute indicates whether the socket will automatically try to reconnect after a small randomized delay:

socket.on("connect_error", (error) => {
if (socket.active) {
// temporary failure, the socket will automatically try to reconnect
} else {
// the connection was denied by the server
// in that case, `socket.connect()` must be manually called in order to reconnect
console.log(error.message);
}
});

disconnect

  • reason <string>

  • details <DisconnectDetails>

断开连接时会触发此事件。

¥This event is fired upon disconnection.

socket.on("disconnect", (reason, details) => {
// ...
});

以下是可能原因的列表:

¥Here is the list of possible reasons:

原因描述自动重连?
io server disconnect服务器已强制断开与 socket.disconnect() 的套接字:X:不
io client disconnect使用 socket.disconnect() 手动断开套接字:X:不
ping timeout服务器未发送 pingInterval + pingTimeout 范围内的 PING:白色复选标记:是的
transport close连接已关闭(例如:用户失去连接,或网络从 WiFi 更改为 4G):白色复选标记:是的
transport error连接遇到错误(例如:服务器在 HTTP 长轮询周期期间被终止):白色复选标记:是的

socket.active 属性表示 socket 是否会在小 随机延迟 后自动尝试重新连接:

¥The socket.active attribute indicates whether the socket will automatically try to reconnect after a small randomized delay:

socket.on("disconnect", (reason) => {
if (socket.active) {
// temporary disconnection, the socket will automatically try to reconnect
} else {
// the connection was forcefully closed by the server or the client itself
// in that case, `socket.connect()` must be manually called in order to reconnect
console.log(reason);
}
});
caution

以下事件名称是保留的,不得在你的应用中使用:

¥The following event names are reserved and must not be used in your application:

  • connect

  • connect_error

  • disconnect

  • disconnecting

  • newListener

  • removeListener

// BAD, will throw an error
socket.emit("disconnect");

完整的 API

¥Complete API

Socket 实例暴露的完整 API 可以参见 此处

¥The complete API exposed by the Socket instance can be found here.