React+Express+Socket.io实时聊天室开发遭遇404错误求助
问题描述
我用React.js和Express开发实时聊天室时遇到404错误:GET http://localhost:3001/socket.io/?EIO=4&transport=polling&t=OjDsdRi 404 (Not Found)
需求是实现消息对所有用户展示,以下是客户端和服务器的部分代码:
Home.js(客户端)
import React from "react"; import NavBar from "../Components/Navs/NavBar"; import io from "socket.io-client"; export default class Home extends React.Component { constructor(props) { super(props); this.state = { userName: "", message: "", messages: [], }; this.inputChange = this.inputChange.bind(this); this.enterChat = this.enterChat.bind(this); this.sendMessage = this.sendMessage.bind(this); } componentDidMount() { // Connect to the Socket.io server this.socket = io("http://localhost:3001"); // Listen for incoming messages this.socket.on("chat message", (msg) => { this.setState((prevState) => ({ messages: [...prevState.messages, msg], })); }); } inputChange(evt) { this.setState({ [evt.target.name]: evt.target.value }); } enterChat() { // Send the user's name to the server, for example this.socket.emit("user entered", this.state.userName); } sendMessage() { // Send the user's message to the server this.socket.emit("chat message", this.state.message); } render() { return ( <> <NavBar /> <div style={{ padding: "15px" }}> <h3>Welcome to my chat</h3> <p>Enter your name</p> <input type="text" onChange={this.inputChange} name="userName" value={this.state.userName} />{" "} <button onClick={this.enterChat}>Enter</button> <div> <h3>Chat Room</h3> <div> {this.state.messages.map((message, index) => ( <div key={index}>{message}</div> ))} </div> <input type="text" onChange={this.inputChange} name="message" value={this.state.message} /> <button onClick={this.sendMessage}>Send Message</button> </div> </div> </> ); } }
app.js(服务器)
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); var cors = require("cors") const http = require('http'); const socketIo = require('socket.io'); const corsOptions = { origin: '*', // Use this for development only methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', credentials: true, optionsSuccessStatus: 204, }; var indexRouter = require('./routes/index'); var message = require('./assets/js/message'); var app = express(); const server = http.createServer(app); const io = socketIo(server); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.use(cors(corsOptions)) app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', indexRouter); app.use('/message', message); // catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)); }); io.on('connection', (socket) => { console.log('A user connected'); socket.on('disconnect', () => { console.log('User disconnected'); }); // You can add custom event handlers here for chat functionality // For example: socket.on('chat message', (msg) => { console.log('Message: ' + msg); // Broadcast the message to all connected clients io.emit('chat message', msg); }); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
我不确定是否需要在./bin/www文件中添加代码,试过排查CORS但没用,求解决方法。
解决方案
这个404错误的核心原因是:你在app.js里创建了绑定Socket.io的server实例,但Express默认启动文件./bin/www并没有使用这个server,而是重新创建了一个新的HTTP服务器运行app,导致Socket.io的路由没有挂载到实际运行的服务器上。
修复步骤如下:
- 修改
app.js的导出内容
把最后一行的module.exports = app;改成:
module.exports = { app, server };
- 修改
./bin/www文件
找到以下代码块:
var app = require('../app'); var http = require('http'); var port = normalizePort(process.env.PORT || '3001'); app.set('port', port); var server = http.createServer(app);
替换为:
var { app, server } = require('../app'); var http = require('http'); var port = normalizePort(process.env.PORT || '3001'); app.set('port', port);
这样就会直接使用app.js中已绑定Socket.io的server实例,而非重新创建新服务器。
- 可选优化:明确Socket.io的CORS配置
为避免潜在跨域问题,初始化Socket.io时可指定客户端地址:
const io = socketIo(server, { cors: { origin: "http://localhost:3000", // 你的React客户端运行地址 methods: ["GET", "POST"] } });
完成修改后重启Express服务器,客户端即可正常连接Socket.io,404错误会消失,消息也能正常广播给所有用户。
内容的提问来源于stack exchange,提问作者moses saleh
相关产品推荐
相关产品推荐

