Socket.io服务端仅接收客户端首个事件问题排查求助
问题:Socket.io客户端连续emit多个事件,服务端仅接收首个事件
我正在开发一款具备实时数据共享功能的React应用,后端采用socket.io与express,前端通过socket.io-client向服务端发送事件。页面加载时我需要发送部分数据至服务端,但当客户端emit多个事件后,服务端控制台仅能接收到首个事件的数据。
前端emit事件代码
import { useEffect, useState } from "react"; import reactLogo from "./assets/react.svg"; import viteLogo from "/vite.svg"; import "./App.css"; import io from "socket.io-client"; const PORT = "http://localhost:3000"; const connectionOptions = { "force new connection": true, reconnectionAttempts: "Infinity", timeout: 10000, retries: 3, transport: ["websocket"], }; const server = io(PORT, connectionOptions); function App() { const [count, setCount] = useState(0); useEffect(() => { server.emit("start"); server.emit("end"); }, []); return ( <> <div> <a href="https://vitejs.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>Vite + React</h1> <div className="card"> <button onClick={() => setCount((count) => count + 1)}> count is {count} </button> <p> Edit <code>src/App.jsx</code> and save to test HMR </p> </div> <p className="read-the-docs"> Click on the Vite and React logos to learn more </p> </> ); } export default App;
服务端监听事件代码
import express from "express"; import http from "http"; import { Server } from "socket.io"; import cors from "cors"; const port = process.env.PORT || 3000; const app = express(); app.use(cors()); const server = http.createServer(app); const io = new Server(server, { cors: { origin: "*", methods: ["GET", "POST"], }, }); io.on("connection", (socket) => { console.log("Connected"); socket.on("start", () => { console.log("start"); }); socket.on("end", () => { console.log("end"); }); socket.on("disconnect", () => { console.log("Disconnected"); }); }); server.listen(port, () => console.log(`server is running on http://localhost:${port}`) ); app.get("/", (req, res) => { res.send("MathCollab server"); });
预期与实际输出
预期服务端控制台输出
Connected start end
实际服务端控制台输出
Connected start
问题原因与解决方法
问题根源
- 连接时机不匹配:组件挂载时直接连续emit事件,但此时socket可能还未完成连接建立,第二个事件发送时连接未就绪,导致事件丢失。
- 废弃配置干扰:
connectionOptions中的"force new connection": true是Socket.io旧版本配置,v4+已废弃,可能引发连接异常。
解决步骤
- 将socket实例初始化移至组件内部,监听
connect事件,确保连接成功后再发送事件。 - 移除废弃的
"force new connection": true配置。
修改后的前端代码
import { useEffect, useState } from "react"; import reactLogo from "./assets/react.svg"; import viteLogo from "/vite.svg"; import "./App.css"; import io from "socket.io-client"; const PORT = "http://localhost:3000"; const connectionOptions = { reconnectionAttempts: "Infinity", timeout: 10000, retries: 3, transport: ["websocket"], }; function App() { const [count, setCount] = useState(0); const [socket, setSocket] = useState(null); useEffect(() => { const newSocket = io(PORT, connectionOptions); // 连接成功后再发送事件 newSocket.on("connect", () => { newSocket.emit("start"); newSocket.emit("end"); }); setSocket(newSocket); // 组件卸载时断开连接 return () => { newSocket.disconnect(); }; }, []); return ( <> <div> <a href="https://vitejs.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>Vite + React</h1> <div className="card"> <button onClick={() => setCount((count) => count + 1)}> count is {count} </button> <p> Edit <code>src/App.jsx</code> and save to test HMR </p> </div> <p className="read-the-docs"> Click on the Vite and React logos to learn more </p> </> ); } export default App;
修改后服务端即可正常接收所有emit的事件。
内容的提问来源于stack exchange,提问作者Abdulbasit Yusuf
相关产品推荐
相关产品推荐

