伺服器選項
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
是否移除沒有任何連線 Socket 的子命名空間。
此選項可能對建立大量動態命名空間有幫助,因為每個命名空間都會建立自己的介面卡執行個體。
啟用此選項(預設為停用)後,當 Socket 從動態命名空間中斷開連線,且沒有其他 Socket 連線到該命名空間時,該命名空間將會被清除,且其介面卡將會關閉。
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
模組的選項清單。可用的選項
- domain
- encode
- expires
- httpOnly
- maxAge
- path
- sameSite
- secure
範例
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'] )。 |
允許的標頭 | 設定 Access-Control-Allow-Headers CORS 標頭。預期為逗號分隔的字串 (例如:'Content-Type,Authorization') 或陣列 (例如:['Content-Type', 'Authorization'] )。如果未指定,預設會反映請求的 Access-Control-Request-Headers 標頭中指定的標頭。 |
公開標頭 | 設定 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 標頭。設為整數以傳遞標頭,否則會省略。 |
預檢持續 | 將 CORS 預檢回應傳遞至下一個處理常式。 |
選項成功狀態 | 提供一個狀態碼,用於成功的 OPTIONS 請求,因為某些舊版瀏覽器 (IE11、各種智慧型電視) 會在 204 時發生錯誤。 |
來源
選項的可能值
布林值
- 將來源
設為true
以反映 請求來源,由req.header('Origin')
定義,或將其設為false
以停用 CORS。字串
- 將來源
設為特定來源。例如,如果你將其設為"http://example.com"
,只有來自 "http://example.com" 的請求才會被允許。RegExp
- 將origin
設定為正規表示式模式,用於測試請求來源。如果符合,請求來源將反映出來。例如,模式/example\.com$/
將反映任何來自以「example.com」結尾的來源的請求。陣列
- 將origin
設定為有效來源的陣列。每個來源可以是字串
或RegExp
。例如,["http://example1.com", /\.example2\.com$/]
將接受來自「http://example1.com"」或「example2.com」的子網域的任何請求。函式
- 將origin
設定為實作一些自訂邏輯的函式。該函式將請求來源作為第一個參數,並將回呼(預期簽章為err [物件],allow [布林值]
)作為第二個參數。
即使有多個網域,選項仍命名為 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)
這定義了在關閉 socket 之前,單一訊息可以包含多少位元組。您可以根據需要增加或減少這個值。
const io = new Server(httpServer, {
maxHttpBufferSize: 1e8
});
它符合 ws 套件的 maxPayload 選項。
perMessageDeflate
歷史記錄
版本 | 變更 |
---|---|
v3.0.0 | permessage-deflate 擴充功能現在預設為停用。 |
v1.4.0 | 首次實作。 |
預設值:false
是否為 WebSocket 傳輸啟用 permessage-deflate 擴充功能。已知此擴充功能會在效能和記憶體消耗方面增加顯著的負擔,因此我們建議僅在真正需要時才啟用它。
請注意,如果將 perMessageDeflate
設定為 false
(這是預設值),則在與 WebSocket 建立連線時,發射時使用的壓縮旗標(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
});