解决连接问题常见/已知问题:
socket 无法连接socket 断开连接socket 卡在 HTTP 长轮询中问题:socket无法连接可能的解释:
您正在尝试访问普通的 WebSocket 服务器服务器无法访问客户端与服务器版本不兼容服务器未发送必要的 CORS 标头您没有启用粘性会话(在多服务器设置中)您正在尝试访问普通的 WebSocket 服务器如"Socket.IO 不是什么"部分所述,Socket.IO 客户端不是 WebSocket 实现,因此无法与 WebSocket 服务器建立连接,即使transports: ["websocket"]:
const socket = io("ws://echo.websocket.org", { transports: ["websocket"]});服务器无法访问请确保 Socket.IO 服务器实际上可以通过给定的 URL 访问。您可以使用以下方法对其进行测试:
curl "
0{"sid":"Lbo5JLzTotvW3g2LAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000}如果不是这种情况,请检查 Socket.IO 服务器是否正在运行,并且两者之间没有任何东西阻止连接。
客户端与服务器版本不兼容这是JS 客户端的兼容性表:
JS 客户端版本Socket.IO 服务器版本1.x2.x3.x4.x1.xYESNONONO2.xNOYESYES1YES13.xNONOYESYES4.xNONOYESYES[1] 使用allowEIO3: true
以下是Java 客户端的兼容性表:
Java 客户端版本Socket.IO 服务器版本2.x3.x4.x1.xYESYES1YES12.xNOYESYES[1] 使用allowEIO3: true
这是Swift 客户端的兼容性表:
Swift 客户端版本Socket.IO 服务器版本2.x3.x4.xv15.xYESYES1YES2v16.xYES3YESYES[1] 使用 allowEIO3: true(服务器)和.connectParams(["EIO": "3"])(客户端):
SocketManager(socketURL: URL(string:"http://localhost:8087/")!, config: [.connectParams(["EIO": "3"])])[2] 使用 allowEIO3: true(服务器)
[3] 使用 .version(.two)(客户端):
SocketManager(socketURL: URL(string:"http://localhost:8087/")!, config: [.version(.two)])服务器未发送必要的 CORS 标头如果您在控制台中看到以下错误:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ...大概意思是:
要么你实际上没有到达 Socket.IO 服务器(见上文)或者您没有在服务器端启用跨域资源共享(CORS)。请在此处查看文档。
您没有启用粘性会话(在多服务器设置中)当扩展到多个 Socket.IO 服务器时,您需要确保给定 Socket.IO 会话的所有请求都到达同一个 Socket.IO 服务器。解释可以在这里找到。
否则将导致 HTTP 400 响应代码:{"code":1,"message":"Session ID unknown"}
请在此处查看文档。
问题: socket 断开连接首先,请注意,即使在稳定的 Internet 连接上,断开连接也很常见并且是意料之中的:
用户和 Socket.IO 服务器之间的任何事情都可能遇到临时故障或重新启动作为自动缩放策略的一部分,服务器本身可能会被终止如果使用移动浏览器,用户可能会失去连接或从 WiFi 切换到 4G浏览器本身可能会冻结非活动选项卡话虽如此,除非另有明确说明,否则Socket.IO 客户端将始终尝试重新连接。
断开连接的可能解释:
浏览器选项卡最小化,心跳失败客户端与服务器版本不兼容你正试图发送一个巨大的有效载荷浏览器选项卡最小化,心跳失败当浏览器选项卡不在焦点上时,某些浏览器(如Chrome)会限制 JavaScript 计时器,这可能会通过Socket.IO v2 中的 ping 超时导致断开连接,因为心跳机制依赖于setTimeout客户端的功能。
作为一种解决方法,您可以增加pingTimeout服务器端的值:
const io = new Server({ pingTimeout: 60000});请注意,升级到 Socket.IO v4(至少socket.io-client@4.1.3,由于这个原因)应该可以防止此类问题,因为心跳机制已被反转(服务器现在发送 PING 数据包)。
客户端与服务器版本不兼容由于通过 WebSocket 传输发送的数据包格式在 v2 和 v3/v4 中相似,因此您可能能够连接不兼容的客户端(见上文),但连接最终会在给定延迟后关闭。
因此,如果您在 30 秒后遇到定期断开连接(这是Socket.IO v2 中pingTimeout 和 pingInterval值的总和),这肯定是由于版本不兼容。
你正试图发送一个巨大的有效载荷如果您在发送大量有效负载时断开连接,这可能意味着您已达到maxHttpBufferSize默认值为 1 MB 的值。请根据您的需要进行调整:
const io = require("socket.io")(httpServer, { maxHttpBufferSize: 1e8});上传时间超过pingTimeout选项值的巨大负载也可能触发断开连接(因为在上传期间heartbeat mechanism失败)。请根据您的需要进行调整:
const io = require("socket.io")(httpServer, { pingTimeout: 60000});问题: socket 卡在 HTTP 长轮询中在大多数情况下,您应该会看到如下内容:
Engine.IO 握手(包含会话 ID — 此处 zBjrh...AAAK — 用于后续请求)tSocket.IO 握手请求(包含auth选项的值)Socket.IO 握手响应(包含Socket#id)WebSocket 连接第一个 HTTP 长轮询请求,一旦建立 WebSocket 连接就关闭如果您没有看到第四个请求的HTTP 101 Switching Protocols响应,这意味着服务器和浏览器之间的某些东西阻止了 WebSocket 连接。
请注意,这不一定是阻塞的,因为连接仍然是通过 HTTP 长轮询建立的,但效率较低。
您可以通过以下方式获取当前传输的名称:
客户端
socket.on("connect", () => { const transport = socket.io.engine.transport.name; // 在大多数情况下, "polling" socket.io.engine.on("upgrade", () => { const upgradedTransport = socket.io.engine.transport.name; // 在大多数情况下, "websocket" });});服务器
io.on("connection", (socket) => { const transport = socket.conn.transport.name; // 在大多数情况下, "polling" socket.conn.on("upgrade", () => { const upgradedTransport = socket.conn.transport.name; // 在大多数情况下, "websocket" });});可能的解释:
服务器前面的代理不接受 WebSocket 连接服务器前面的代理不接受 WebSocket 连接请在此处查看文档。