You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的路由没有挂载到实际运行的服务器上。

修复步骤如下:

  1. 修改app.js的导出内容
    把最后一行的module.exports = app;改成:
module.exports = { app, server };
  1. 修改./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实例,而非重新创建新服务器。

  1. 可选优化:明确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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:43:21