用戶端選項
IO 工廠選項
forceNew
預設值:false
是否建立新的 Manager 實例。
Manager 實例負責與伺服器進行低層級連線(透過 HTTP 長輪詢或 WebSocket 建立)。它會處理重新連線的邏輯。
Socket 實例是介面,用於傳送事件至伺服器(以及從伺服器接收事件)。它屬於指定的 命名空間。
單一 Manager 可以附加至多個 Socket 實例。
下列範例將為 3 個 Socket 實例(單一 WebSocket 連線)重複使用相同的 Manager 實例
const socket = io("https://example.com"); // the main namespace
const productSocket = io("https://example.com/product"); // the "product" namespace
const orderSocket = io("https://example.com/order"); // the "order" namespace
下列範例將建立 3 個不同的 Manager 實例(以及 3 個不同的 WebSocket 連線)
const socket = io("https://example.com"); // the main namespace
const productSocket = io("https://example.com/product", { forceNew: true }); // the "product" namespace
const orderSocket = io("https://example.com/order", { forceNew: true }); // the "order" namespace
重複使用現有命名空間也會每次建立新的 Manager
const socket1 = io(); // 1st manager
const socket2 = io(); // 2nd manager
const socket3 = io("/admin"); // reuse the 1st manager
const socket4 = io("/admin"); // 3rd manager
multiplex
預設值:true
forceNew
的反義詞:是否重複使用現有的 Manager 執行個體。
const socket = io(); // 1st manager
const adminSocket = io("/admin", { multiplex: false }); // 2nd manager
低階引擎選項
這些設定會由附加至相同 Manager 的所有 Socket 執行個體共用。
addTrailingSlash
於 v4.6.0 新增
預設會新增的尾斜線現在可以停用
import { io } from "socket.io-client";
const socket = io("https://example.com", {
addTrailingSlash: false
});
在上述範例中,請求 URL 會是 https://example.com/socket.io
,而不是 https://example.com/socket.io/
。
autoUnref
於 v4.0.0 新增
預設值:false
將 autoUnref
設為 true
時,Socket.IO 程式端將允許程式在事件系統中沒有其他活動計時器/TCP Socket 時結束(即使程式端已連線)。
import { io } from "socket.io-client";
const socket = io({
autoUnref: true
});
另請參閱:https://node.dev.org.tw/api/timers.html#timeoutunref
closeOnBeforeunload
歷程
版本 | 變更 |
---|---|
v4.7.1 | 此選項現在預設為 false 。 |
v4.1.0 | 首次實作。 |
預設值:false
在瀏覽器中發出 beforeunload
事件時,是否(靜默地)關閉連線。
當此選項設為 false
(預設值)時,Socket 執行個體會在使用者重新載入頁面時發出 disconnect
事件(在 Firefox 上)
此行為只會發生在 Firefox 上,在其他瀏覽器上,Socket 執行個體在使用者重新載入頁面時不會發出任何 disconnect
事件。
當此選項設為 true
時,所有瀏覽器都會有相同的行為(重新載入頁面時不會有 disconnect
事件)
如果你在應用程式中使用 beforeunload
事件(「你確定要離開此頁面嗎?」),建議將此選項設為 false
。
請查看 此問題 以取得更多資訊。
extraHeaders
預設值:-
額外的標頭(然後在伺服器端的 socket.handshake.headers
物件中找到)。
範例
客戶端
import { io } from "socket.io-client";
const socket = io({
extraHeaders: {
"my-custom-header": "1234"
}
});
伺服器
io.on("connection", (socket) => {
console.log(socket.handshake.headers); // an object containing "my-custom-header": "1234"
});
在瀏覽器環境中,如果你只啟用 WebSocket 傳輸,extraHeaders
選項將會被忽略,因為瀏覽器中的 WebSocket API 不允許提供自訂標頭。
import { io } from "socket.io-client";
const socket = io({
transports: ["websocket"],
extraHeaders: {
"my-custom-header": "1234" // ignored
}
});
不過,這將在 Node.js 或 React-Native 中運作。
forceBase64
預設值:false
是否強制對透過 WebSocket 傳送的二進位內容進行 base64 編碼(HTTP 長輪詢始終啟用)。
path
預設值:/socket.io/
這是伺服器端擷取的路徑名稱。
伺服器和客戶端的值必須相符(除非你在中間使用路徑改寫代理)。
客戶端
import { io } from "socket.io-client";
const socket = io("https://example.com", {
path: "/my-custom-path/"
});
伺服器
import { createServer } from "http";
import { Server } from "socket.io";
const httpServer = createServer();
const io = new Server(httpServer, {
path: "/my-custom-path/"
});
請注意,這與 URI 中的路徑不同,URI 中的路徑代表 命名空間。
範例
import { io } from "socket.io-client";
const socket = io("https://example.com/order", {
path: "/my-custom-path/"
});
- Socket 實例附加到「order」命名空間
- HTTP 要求看起來像:
GET https://example.com/my-custom-path/?EIO=4&transport=polling&t=ML4jUwU
protocols
在 v2.0.0 中新增
預設值:-
單一協定字串或協定字串陣列。這些字串用於表示子協定,以便單一伺服器可以實作多個 WebSocket 子協定(例如,你可能希望一個伺服器能夠根據指定的協定處理不同類型的互動)。
import { io } from "socket.io-client";
const socket = io({
transports: ["websocket"],
protocols: ["my-protocol-v1"]
});
伺服器
io.on("connection", (socket) => {
const transport = socket.conn.transport;
console.log(transport.socket.protocol); // prints "my-protocol-v1"
});
參考資料
- https://datatracker.ietf.org/doc/html/rfc6455#section-1.9
- https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket
query
預設值:-
其他查詢參數(然後在伺服器端的 socket.handshake.query
物件中找到)。
範例
客戶端
import { io } from "socket.io-client";
const socket = io({
query: {
x: 42
}
});
伺服器
io.on("connection", (socket) => {
console.log(socket.handshake.query); // prints { x: "42", EIO: "4", transport: "polling" }
});
查詢參數無法在會話期間更新,因此在用戶端變更 query
只有在目前會話關閉且產生新會話時才會生效。
socket.io.on("reconnect_attempt", () => {
socket.io.opts.query.x++;
});
注意:下列查詢參數已保留,且無法在您的應用程式中使用。
EIO
:通訊協定的版本(目前為「4」)transport
:傳輸名稱(「polling」或「websocket」)sid
:會話 IDj
:如果傳輸為輪詢,但需要 JSONP 回應t
:用於快取破解的雜湊時間戳
rememberUpgrade
預設值:false
如果為 true,且與伺服器先前的 WebSocket 連線成功,連線嘗試將會略過正常的升級程序,且最初會嘗試 WebSocket。傳輸錯誤後進行的連線嘗試將會使用正常的升級程序。建議您僅在使用 SSL/TLS 連線時開啟此功能,或如果您知道您的網路不會封鎖 Websocket。
timestampParam
預設值:"t"
做為時間戳記金鑰使用的查詢參數名稱。
timestampRequests
預設值:true
是否將時間戳記查詢參數新增至每個要求(用於快取破解)。
transportOptions
在 v2.0.0 中新增
預設值:{}
傳輸特定的選項。
範例
import { io } from "socket.io-client";
const socket = io({
path: "/path-for-http-long-polling/",
transportOptions: {
websocket: {
path: "/path-for-websocket/"
}
}
});
transports
歷程
版本 | 變更 |
---|---|
v4.7.0 | 新增 webtransport 。 |
v1.0.0 | 首次實作。 |
預設值:["polling", "websocket", "webtransport"]
與 Socket.IO 伺服器之間的低階連線可以透過下列方式建立:
- HTTP 長輪詢:連續的 HTTP 要求(寫入用
POST
,讀取用GET
) - WebSocket
- WebTransport
下列範例停用 HTTP 長輪詢傳輸。
const socket = io("https://example.com", { transports: ["websocket"] });
注意:在這種情況下,伺服器端不需要黏著式會話(更多資訊 在此)。
預設情況下,會先建立 HTTP 長輪詢連線,然後再嘗試升級至 WebSocket(說明 在此)。您可以先使用 WebSocket,方法如下:
const socket = io("https://example.com", {
transports: ["websocket", "polling"] // use WebSocket first, if available
});
socket.on("connect_error", () => {
// revert to classic upgrade
socket.io.opts.transports = ["polling", "websocket"];
});
一個可能的不利之處是,只有在 WebSocket 連線建立失敗時,才會檢查您的 CORS 設定 的有效性。
upgrade
預設值:true
客戶端是否應嘗試將傳輸從 HTTP 長輪詢升級為更好的方式。
withCredentials
歷程
版本 | 變更 |
---|---|
v4.7.0 | Node.js 客戶端現在會遵守 withCredentials 設定。 |
v3.0.0 | withCredentials 現在預設為 false 。 |
v1.0.0 | 首次實作。 |
預設值:false
跨網站要求是否應包含憑證,例如 Cookie、授權標頭或 TLS 客戶端憑證。設定 withCredentials
對同網站要求沒有影響。
import { io } from "socket.io-client";
const socket = io("https://my-backend.com", {
withCredentials: true
});
伺服器需要傳送正確的 Access-Control-Allow-*
標頭以允許連線
import { createServer } from "http";
import { Server } from "socket.io";
const httpServer = createServer();
const io = new Server(httpServer, {
cors: {
origin: "https://my-frontend.com",
credentials: true
}
});
設定 withCredentials
為 true
時,不能使用 origin: *
。這會觸發下列錯誤
跨來源要求遭封鎖:同來源政策禁止讀取遠端資源 '.../socket.io/?EIO=4&transport=polling&t=NvQfU77'。(原因:如果 CORS 標頭 'Access-Control-Allow-Origin' 為 ' *',則不支援憑證)
文件
從版本 4.7.0
開始,當將 withCredentials
選項設定為 true
時,Node.js 客戶端現在會在 HTTP 要求中包含 Cookie,讓與基於 Cookie 的固定工作階段搭配使用變得更為容易。
Node.js 特定選項
支援下列選項
agent
pfx
key
passphrase
cert
ca
ciphers
rejectUnauthorized
請參閱 Node.js 文件
使用自簽署憑證的範例
客戶端
import { readFileSync } from "fs";
import { io } from "socket.io-client";
const socket = io("https://example.com", {
ca: readFileSync("./cert.pem")
});
伺服器
import { readFileSync } from "fs";
import { createServer } from "https";
import { Server } from "socket.io";
const httpServer = createServer({
cert: readFileSync("./cert.pem"),
key: readFileSync("./key.pem")
});
const io = new Server(httpServer);
使用客戶端憑證驗證的範例
客戶端
import { readFileSync } from "fs";
import { io } from "socket.io-client";
const socket = io("https://example.com", {
ca: readFileSync("./server-cert.pem"),
cert: readFileSync("./client-cert.pem"),
key: readFileSync("./client-key.pem"),
});
伺服器
import { readFileSync } from "fs";
import { createServer } from "https";
import { Server } from "socket.io";
const httpServer = createServer({
cert: readFileSync("./server-cert.pem"),
key: readFileSync("./server-key.pem"),
requestCert: true,
ca: [
readFileSync("client-cert.pem")
]
});
const io = new Server(httpServer);
rejectUnauthorized
是 Node.js 專屬選項,它不會繞過瀏覽器中的安全性檢查
管理員選項
這些設定會由附加至相同 Manager 的所有 Socket 執行個體共用。
autoConnect
預設值:true
是否在建立時自動連線。如果設定為 false
,您需要手動連線
import { io } from "socket.io-client";
const socket = io({
autoConnect: false
});
socket.connect();
// or
socket.io.open();
parser
新增於 v2.2.0
預設值:require("socket.io-parser")
用於封送/解封送封包的剖析器。請參閱此處以取得更多資訊。
randomizationFactor
預設值:0.5
重新連線時使用的隨機化因子(例如,讓用戶端在伺服器當機後不會在完全相同的時間重新連線)。
預設值範例
- 第 1 次重新連線嘗試發生於 500 至 1500 毫秒之間(
1000 * 2^0 * (<介於 -0.5 至 1.5 之間的某個值>)
) - 第 2 次重新連線嘗試發生於 1000 至 3000 毫秒之間(
1000 * 2^1 * (<介於 -0.5 至 1.5 之間的某個值>)
) - 第 3 次重新連線嘗試發生於 2000 至 5000 毫秒之間(
1000 * 2^2 * (<介於 -0.5 至 1.5 之間的某個值>)
) - 後續重新連線嘗試發生於 5000 毫秒之後
reconnection
預設值:true
是否啟用重新連線。如果設為 false
,您需要手動重新連線
import { io } from "socket.io-client";
const socket = io({
reconnection: false
});
const tryReconnect = () => {
setTimeout(() => {
socket.io.open((err) => {
if (err) {
tryReconnect();
}
});
}, 2000);
}
socket.io.on("close", tryReconnect);
reconnectionAttempts
預設值:Infinity
放棄前嘗試重新連線的次數。
reconnectionDelay
預設值:1000
重新連線前的初始延遲(毫秒),受 randomizationFactor 值影響。
reconnectionDelayMax
預設值:5000
兩次重新連線嘗試之間的最大延遲。每次嘗試會將重新連線延遲增加 2 倍。
timeout
預設值:20000
每次連線嘗試的逾時時間(毫秒)。
Socket 選項
這些設定是特定於給定的 Socket 實例。
ackTimeout
於 v4.6.0 新增
預設值:-
等待確認時使用的預設逾時時間(毫秒)(不要與現有的 timeout 選項混淆,後者由管理員在連線期間使用)
auth
新增於 v3.0.0
預設值:-
存取名稱空間時傳送的憑證(另請參閱 此處)。
範例
客戶端
import { io } from "socket.io-client";
const socket = io({
auth: {
token: "abcd"
}
});
// or with a function
const socket = io({
auth: (cb) => {
cb({ token: localStorage.token })
}
});
伺服器
io.on("connection", (socket) => {
console.log(socket.handshake.auth); // prints { token: "abcd" }
});
當拒絕存取名稱空間時,你可以更新 auth
地圖
socket.on("connect_error", (err) => {
if (err.message === "invalid credentials") {
socket.auth.token = "efgh";
socket.connect();
}
});
或手動強制 Socket 實例重新連線
socket.auth.token = "efgh";
socket.disconnect().connect();
retries
於 v4.6.0 新增
預設值:-
最大重試次數。超過限制,封包將會被捨棄。
const socket = io({
retries: 3,
ackTimeout: 10000
});
// implicit ack
socket.emit("my-event");
// explicit ack
socket.emit("my-event", (err, val) => { /* ... */ });
// custom timeout (in that case the ackTimeout is optional)
socket.timeout(5000).emit("my-event", (err, val) => { /* ... */ });