服务器选项
Socket.IO 服务器选项
以下选项会影响 Socket.IO 服务器的行为。
adapter
默认值: require("socket.io-adapter")
(内存适配器,其源代码可以在 这里 找到)
要使用的 "适配器"。
使用 Redis 适配器 的示例
- CommonJS
- ES 模块
- TypeScript
const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/redis-adapter");
const { createClient } = require("redis");
const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";
const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";
const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
cleanupEmptyChildNamespaces
在 v4.6.0 中添加
默认值: false
是否删除 子命名空间,这些命名空间没有连接到它们的套接字。
如果您创建了许多动态命名空间,此选项可能很有用,因为每个命名空间都会创建自己的适配器实例。
启用此选项(默认情况下禁用)后,当套接字从动态命名空间断开连接时,如果没有任何其他套接字连接到它,则该命名空间将被清理,并且它的适配器将被关闭。
connectionStateRecovery
在 v4.6.0 中添加
默认值: undefined
用于 连接状态恢复 功能的选项
const io = new Server(httpServer, {
connectionStateRecovery: {
// the backup duration of the sessions and the packets
maxDisconnectionDuration: 2 * 60 * 1000,
// whether to skip middlewares upon successful recovery
skipMiddlewares: true,
}
});
如果 skipMiddlewares
选项设置为 true
,则在成功恢复连接时将跳过中间件
function computeUserIdFromHeaders(headers) {
// to be implemented
}
// this middleware will be skipped if the connection is successfully recovered
io.use(async (socket, next) => {
socket.data.userId = await computeUserIdFromHeaders(socket.handshake.headers);
next();
});
io.on("connection", (socket) => {
// the userId attribute will either come:
// - from the middleware above (first connection or failed recovery)
// - from the recevery mechanism
console.log("userId", socket.data.userId);
});
connectTimeout
默认值: 45000
在断开尚未成功加入命名空间的客户端连接之前的毫秒数。
parser
默认值: socket.io-parser
要使用的解析器。请参阅 此处 的文档。
path
默认值: /socket.io/
它是服务器端捕获的路径的名称。
服务器和客户端的值必须匹配(除非您在两者之间使用路径重写代理)。
服务器
import { createServer } from "http";
import { Server } from "socket.io";
const httpServer = createServer();
const io = new Server(httpServer, {
path: "/my-custom-path/"
});
客户端
import { io } from "socket.io-client";
const socket = io("https://example.com", {
path: "/my-custom-path/"
});
serveClient
默认值: true
是否提供客户端文件。如果为 true
,则不同的捆绑包将在以下位置提供
<url>/socket.io/socket.io.js
<url>/socket.io/socket.io.min.js
<url>/socket.io/socket.io.msgpack.min.js
(包括它们相关的源映射)
另请参阅 此处。
底层引擎选项
以下选项会影响底层 Engine.IO 服务器的行为。
addTrailingSlash
在 v4.6.0 中添加
默认值: true
现在可以禁用默认情况下添加的尾部斜杠
import { createServer } from "node:http";
import { Server } from "socket.io";
const httpServer = createServer();
const io = new Server(httpServer, {
addTrailingSlash: false
});
在上面的示例中,客户端可以省略尾部斜杠,并使用 /socket.io
而不是 /socket.io/
。
allowEIO3
默认值: false
是否启用与 Socket.IO v2 客户端的兼容性。
另请参阅:从 2.x 迁移到 3.0
示例
const io = new Server(httpServer, {
allowEIO3: true // false by default
});
allowRequest
默认值: -
一个函数,它接收给定的握手或升级请求作为其第一个参数,并且可以决定是否继续。
示例
const io = new Server(httpServer, {
allowRequest: (req, callback) => {
const isOriginValid = check(req);
callback(null, isOriginValid);
}
});
这也可以与 initial_headers
事件结合使用,向客户端发送 cookie
import { serialize } from "cookie";
const io = new Server(httpServer, {
allowRequest: async (req, callback) => {
const session = await fetchSession(req);
req.session = session;
callback(null, true);
}
});
io.engine.on("initial_headers", (headers, req) => {
if (req.session) {
headers["set-cookie"] = serialize("sid", req.session.id, { sameSite: "strict" });
}
});
另请参阅
allowUpgrades
默认值: true
是否允许传输升级。
cookie
默认值: -
将转发到 cookie
模块的选项列表。可用选项
- 域
- 编码
- 过期
- httpOnly
- maxAge
- 路径
- sameSite
- 安全
示例
import { Server } from "socket.io";
const io = new Server(httpServer, {
cookie: {
name: "my-cookie",
httpOnly: true,
sameSite: "strict",
maxAge: 86400
}
});
从 Socket.IO v3 开始,不再默认发送 cookie (参考)。
cors
默认值: -
将转发到 cors
模块的选项列表。更多信息可以在 此处 找到。
示例
- 允许给定的来源
const io = new Server(httpServer, {
cors: {
origin: ["https://example.com"]
}
});
- 允许给定的来源用于本地开发
const io = new Server(httpServer, {
cors: {
origin: process.env.NODE_ENV === "production" ? false : ["http://localhost:3000"]
}
});
- 允许给定的来源、标头和凭据(例如 cookie、授权标头或 TLS 客户端证书)
const io = new Server(httpServer, {
cors: {
origin: ["https://example.com", "https://dev.example.com"],
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
如果您希望浏览器发送凭据(例如 cookie、授权标头或 TLS 客户端证书),您还需要在客户端设置 withCredentials
选项为 true
import { io } from "socket.io-client";
const socket = io("https://my-backend.com", {
withCredentials: true
});
更多信息 此处。
- 允许任何来源
const io = new Server(httpServer, {
cors: {
origin: "*"
}
});
请注意,在这种情况下,您实际上是在禁用跨源资源共享 (CORS) 提供的安全性,因为任何域都可以访问您的服务器。请谨慎使用。
可用选项
选项 | 描述 |
---|---|
来源 | 配置 Access-Control-Allow-Origin CORS 标头。 |
方法 | 配置 Access-Control-Allow-Methods CORS 标头。需要逗号分隔的字符串(例如:'GET,PUT,POST')或数组(例如:['GET', 'PUT', 'POST'] )。 |
allowedHeaders | 配置 Access-Control-Allow-Headers CORS 标头。需要逗号分隔的字符串(例如:'Content-Type,Authorization')或数组(例如:['Content-Type', 'Authorization'] )。如果未指定,则默认为反映请求的 Access-Control-Request-Headers 标头中指定的标头。 |
exposedHeaders | 配置 Access-Control-Expose-Headers CORS 标头。需要逗号分隔的字符串(例如:'Content-Range,X-Content-Range')或数组(例如:['Content-Range', 'X-Content-Range'] )。如果未指定,则不会公开任何自定义标头。 |
凭据 | 配置 Access-Control-Allow-Credentials CORS 标头。设置为 true 以传递标头,否则将省略。 |
maxAge | 配置 Access-Control-Max-Age CORS 标头。设置为整数以传递标头,否则将省略。 |
preflightContinue | 将 CORS 预检响应传递给下一个处理程序。 |
optionsSuccessStatus | 提供一个状态代码用于成功的 OPTIONS 请求,因为一些旧的浏览器(IE11、各种智能电视)无法处理 204 。 |
origin
选项的可能值
Boolean
- 将origin
设置为true
以反映 请求来源,如req.header('Origin')
所定义,或将其设置为false
以禁用 CORS。String
- 将origin
设置为特定来源。例如,如果您将其设置为"http://example.com"
,则只允许来自 "http://example.com" 的请求。RegExp
- 将origin
设置为将用于测试请求来源的正则表达式模式。如果匹配,则将反映请求来源。例如,模式/example\.com$/
将反映来自以“example.com”结尾的来源的任何请求。Array
- 将origin
设置为有效来源的数组。每个来源可以是String
或RegExp
。例如,["http://example1.com", /\.example2\.com$/]
将接受来自 "http://example1.com" 或来自“example2.com”的子域的任何请求。Function
- 将origin
设置为实现某些自定义逻辑的函数。该函数将请求来源作为第一个参数,并将回调(它期望签名err [object], allow [bool]
)作为第二个参数。
即使有多个域,选项的名称也是 origin
(而不是 origins
)
const io = new Server(httpServer, {
cors: {
// BAD
origins: ["https://example.com"],
// GOOD
origin: ["https://example.com"],
}
});
在设置 credentials: true
时,您不能使用 origin: "*"
// THIS WON'T WORK
const io = new Server(httpServer, {
cors: {
origin: "*",
credentials: true
}
});
您将在浏览器控制台中看到类似这样的错误
跨源请求被阻止:同源策略不允许读取远程资源位于‘.../socket.io/?EIO=4&transport=polling&t=NvQfU77’。(原因:如果 CORS 标头‘Access-Control-Allow-Origin’为‘*’,则不支持凭据)
您需要提供域列表(推荐解决方案)或使用以下方法
const io = new Server(httpServer, {
cors: {
origin: (_req, callback) => {
callback(null, true);
},
credentials: true
}
});
请注意,在这种情况下,与 origin: "*"
或 origin: true
一样,您实际上是在禁用跨源资源共享 (CORS) 提供的安全性,因为任何域都可以访问您的服务器。请谨慎使用。
httpCompression
在 v1.4.0 中添加
默认值: true
是否为 HTTP 长轮询传输启用压缩。
请注意,如果 httpCompression
设置为 false
,则在使用 HTTP 长轮询请求建立连接时,在发出时使用的压缩标志 (socket.compress(true).emit(...)
) 将被忽略。
支持来自 Node.js zlib
模块 的所有选项。
示例
const io = new Server(httpServer, {
httpCompression: {
// Engine.IO options
threshold: 2048, // defaults to 1024
// Node.js zlib options
chunkSize: 8 * 1024, // defaults to 16 * 1024
windowBits: 14, // defaults to 15
memLevel: 7, // defaults to 8
}
});
maxHttpBufferSize
默认值:1e6
(1 MB)
这定义了单个消息在关闭套接字之前可以包含多少字节。您可以根据需要增加或减少此值。
const io = new Server(httpServer, {
maxHttpBufferSize: 1e8
});
它与 ws 包的 maxPayload 选项匹配。
perMessageDeflate
历史
版本 | 更改 |
---|---|
v3.0.0 | permessage-deflate 扩展现在默认情况下已禁用。 |
v1.4.0 | 首次实现。 |
默认值: false
是否为 WebSocket 传输启用 permessage-deflate 扩展。众所周知,此扩展在性能和内存消耗方面会增加大量开销,因此我们建议仅在确实需要时才启用它。
请注意,如果 perMessageDeflate
设置为 false
(这是默认值),则在使用 WebSockets 建立连接时,在发出时使用的压缩标志 (socket.compress(true).emit(...)
) 将被忽略,因为 permessage-deflate 扩展不能在每个消息的基础上启用。
支持来自 ws
模块 的所有选项
const io = new Server(httpServer, {
perMessageDeflate: {
threshold: 2048, // defaults to 1024
zlibDeflateOptions: {
chunkSize: 8 * 1024, // defaults to 16 * 1024
},
zlibInflateOptions: {
windowBits: 14, // defaults to 15
memLevel: 7, // defaults to 8
},
clientNoContextTakeover: true, // defaults to negotiated value.
serverNoContextTakeover: true, // defaults to negotiated value.
serverMaxWindowBits: 10, // defaults to negotiated value.
concurrencyLimit: 20, // defaults to 10
}
});
pingInterval
默认值:25000
此值用于心跳机制,该机制定期检查服务器和客户端之间的连接是否仍然存活。
服务器每 pingInterval
毫秒发送一个 ping 数据包,如果客户端在 pingTimeout
毫秒内没有用 pong 响应,则服务器认为连接已关闭。
类似地,如果客户端在 pingInterval + pingTimeout
毫秒内没有从服务器收到 ping 数据包,则客户端也认为连接已关闭。
在这两种情况下,断开连接的原因将是:ping 超时
socket.on("disconnect", (reason) => {
console.log(reason); // "ping timeout"
});
使用像 1000
这样的小值(每秒一次心跳)会给您的服务器带来一些负载,这在数千个连接的客户端中可能会变得明显。
pingTimeout
历史
版本 | 更改 |
---|---|
v4.0.0 | pingTimeout 现在默认为 20000 毫秒。 |
v2.1.0 | 默认为 5000 毫秒。 |
v1.0.0 | 默认为 60000 毫秒。 |
默认值:20000
参见 上面。
使用较小的值意味着暂时无响应的服务器可能会触发许多客户端重新连接。
相反,使用较大的值意味着断开的连接需要更长时间才能被检测到(如果 pingInterval + pingTimeout
大于 60 秒,您可能会在 React Native 上收到警告)。
transports
默认值:["polling", "websocket"]
服务器端允许的低级传输。
启用 WebTransport 的示例
const io = new Server({
transports: ["polling", "websocket", "webtransport"]
});
请查看 WebTransport 示例 这里。
另请参见:客户端 transports
upgradeTimeout
默认值:10000
这是取消未完成的传输升级之前的延迟(以毫秒为单位)。
wsEngine
默认值:require("ws").Server
(源代码可以在 这里 找到)
要使用的 WebSocket 服务器实现。请参见 这里 的文档。
示例
const io = new Server(httpServer, {
wsEngine: require("eiows").Server
});