【问题标题】:Sending data from the client to the server and displaying to the terminal using `sockets`将数据从客户端发送到服务器并使用“套接字”显示到终端
【发布时间】:2021-07-27 00:18:56
【问题描述】:

在客户端,它在useEffect 中调用socket.current.emit。我正在尝试将姓名和年龄发送到服务器并在服务器端io.on 终端中显示数据。我没有错误,终端没有显示任何内容。

后台

server.js

const express = require('express');
require('dotenv').config();

const app = express();
const port = process.env.PORT || 8000;

const server = app.listen(port, () => {
    console.log(`connect on the port ${port} - ${process.env.NODE_ENV}`);
});

const io = require('socket.io').listen(server);


io.on('connection', socket => {
    socket.on('hello', data => {
      console.log({name: data.name, age: data.age});
    });
});

前端

客户

import React, { useState, useRef, useEffect } from 'react';
import io from 'socket.io-client';


const ChatUser = () => {

    const [values, setValues] = useState({
        chatters: [],
        idReceiver: '',
        idSender: ''
    });

    const [activeUser, setActiveUser] = useState('');
    const [message, setMessage] = useState('');
    const [chats, setChats] = useState([]);

    const socket = useRef();
    

    useEffect(() => {

        if(!socket.current) {
            socket.current = io(process.env.REACT_APP_API);
        }

        if(socket.current) {
            socket.current.emit('hello', {name: 'john', age: '23'});
        }
    }, []);


    return (
        <>  

        </>
    );
};

//env
REACT_APP_API=http://localhost:8000/api

更新的后端

我在 server.js 中的代码也许我应该把 io.on 放在不同的地方?

const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const db = require('./connection');
const app = express();


// Connect to our Database and handle an bad connections
mongoose
    .connect(process.env.DATABASE, { 
        autoIndex: false
    })
    .then(() => console.log("DB server connect"))
    .catch(() => console.log("DB server disconnect"))


const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/user');
const messageRoutes = require('./routes/message');
const countriesRoutes = require('./routes/countries');
const languagesRoutes = require('./routes/languages');
const tutorRoutes = require('./routes/tutor');

app.use(morgan('dev'));
app.use(bodyParser.json({limit: '50mb'}));

app.use((req,res,next)=>{
    res.header('Content-Type: application/json');
    res.header('Access-Control-Allow-Origin','*'); 
    res.header('Access-Control-Allow-Headers','Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Access-Control-Allow-Request-Method');
    res.header('Access-Control-Allow-Methods','GET, PUT, POST, DELETE, OPTIONS');
    res.header('Allow','GET, PUT, POST, DELETE, OPTIONS');

    req.io = io;
    next();
});

if(process.env.NODE_ENV === 'development') {

    app.use(cors());

}

const port = process.env.PORT || 8000;

const server = app.listen(port, () => {
    console.log(`connect on the port ${port} - ${process.env.NODE_ENV}`);
});


const io = require('socket.io').listen(server, {
  cors: {
    origin: '*'
  }
});


io.on('connection', socket => {
    socket.on('hello', data => {
      console.log({name: data.name, age: data.age});
    });
});


//middleware
app.use('/api', authRoutes);
app.use('/api', userRoutes);
app.use('/api', countriesRoutes);
app.use('/api', languagesRoutes);
app.use('/api', tutorRoutes);
app.use('/api', messageRoutes);

请求标头

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: localhost:8000
Origin: http://localhost:3000
Referer: http://localhost:3000/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36

404 未找到 - 在终端中

GET /socket.io/?EIO=4&amp;transport=polling&amp;t=NtFERz- 404

【问题讨论】:

  • 您确定浏览器控制台没有错误吗?我测试了你的代码,我在浏览器上看到了 CORS 错误。如果您可以确认您也在浏览器上收到此错误,那么此答案应该会有所帮助。 stackoverflow.com/a/38749535/6338245
  • @FahadFarooq 我在文件 server.js 中添加了我的完整代码。也许我应该把io.on 放在不同的地方或更改订单功能?
  • 当我运行你的后端代码时,我得到TypeError: require(...).listen is not a function在线:const io = require("socket.io").listen(server, {。你使用的是哪个版本的socket.io
  • NVM,这里的问题是您尝试连接到错误的 url。
  • @FahadFarooq "socket.io-client": "^3.0.5",

标签: javascript node.js reactjs express sockets


【解决方案1】:

您没有正确组合 expresssocket 来设置服务器。

您还可以观看此视频:

React and Socket.io with Express in 15 minutes

服务器 - 后端

按照以下步骤操作:

  1. 内置 HTTP 模块
    • Node.js 有一个名为 HTTP 的内置模块,它允许 Node.js 通过超文本传输​​协议 (HTTP) 传输数据。 HTTP 模块可以创建一个 HTTP 服务器来侦听服务器端口并将响应返回给客户端。
    • 使用createServer()方法创建HTTP服务器:
const http = require("http");
const express = require("express");
const app = express();

const server = http.createServer(app);
  1. 创建一个具有自定义名称的实用程序文件,这里是这个 socketUtils.js 的名称:
    • 在这里,我们使用自定义配置设置套接字,并实例化。
// <root-project-dir>/utils/socketUtils.js

const socketIO = require("socket.io");

exports.sio = (server) => {
  return socketIO(server, {
    transports: ["polling"],
    cors: {
      origin: "*",
    },
  });
};

exports.connection = (io) => {
  io.on("connection", (socket) => {
    console.log("A user is connected");

    socket.on("message", (message) => {
      console.log(`message from ${socket.id} : ${message}`);
    });

    socket.on("disconnect", () => {
      console.log(`socket ${socket.id} disconnected`);
    });
  });
};
  1. 现在是时候使用socketUtils.js 文件了:
const http = require("http");
const dotenv = require("dotenv");
const cors = require("cors");

dotenv.config({
  path: "./config.env",
});

const express = require("express");
const app = express();
const socketUtils = require("./utils/socketUtils");

const server = http.createServer(app);
const io = socketUtils.sio(server);
socketUtils.connection(io);
  1. 创建套接字中间件:
    • 为了在每个请求中全局访问套接字,我们创建了一个中间件。
const socketIOMiddleware = (req, res, next) => {
  req.io = io;

  next();
};
  1. 使用listen() 方法:
    • 您可以根据需要的路由存在的优先级编写其他中间件,然后将listen()方法放在最后。
// CORS
app.use(cors());

// ROUTES
app.use("/api/v1/hello", socketIOMiddleware, (req, res) => {
  req.io.emit("message", `Hello, ${req.originalUrl}`);
  res.send("hello world!");
});

// LISTEN
const port = process.env.PORT || 8000;
server.listen(port, () => {
  console.log(`App running on port ${port}...`);
});

最终文件应如下所示:

// <root-project-dir>/index.js

const http = require("http");
const dotenv = require("dotenv");
const cors = require("cors");

dotenv.config({
  path: "./config.env",
});

const express = require("express");
const app = express();
const socketUtils = require("./utils/socketUtils");

const server = http.createServer(app);
const io = socketUtils.sio(server);
socketUtils.connection(io);

const socketIOMiddleware = (req, res, next) => {
  req.io = io;

  next();
};

// CORS
app.use(cors());

// ROUTES
app.use("/api/v1/hello", socketIOMiddleware, (req, res) => {
  req.io.emit("message", `Hello, ${req.originalUrl}`);
  res.send("hello world!");
});

// LISTEN
const port = process.env.PORT || 8000;
server.listen(port, () => {
  console.log(`App running on port ${port}...`);
});

最后,要测试服务器,可以使用SocketIO Client Tool 在线工具,非常有用。


客户 - 前端

设置好服务器后,你可以在 React 应用中按如下方式使用它并发出事件:

import { useEffect, useRef } from "react";
import "./App.css";

import { io } from "socket.io-client";

function App() {
  const socket = useRef();

  useEffect(() => {
    socket.current = io("ws://localhost:9013");

    socket.current.on("connnection", () => {
      console.log("connected to server");
    });
  }, []);

  const handleClick = () => {
    socket.current.emit("message", new Date().getTime());
  };

  return (
    <div className="App">
      <p>Socket.io app</p>

      <button type="button" onClick={handleClick}>
        Emit a time message
      </button>
    </div>
  );
}

export default App;

最后,您可以通过以下链接访问 GitHub repo 中的源代码: https://github.com/mohammadoftadeh/simple-react-socket-io

【讨论】:

  • 它对我不起作用。我在开发工具浏览器“请求 URL:localhost:8900/socket.io/…”选项卡“网络”中看到它是红色
  • @Umbro。它工作正常,您肯定做错了一些部分,因为它已经过测试,并且在我链接到的视频教程中一切正常。 youtu.be/SMubOngCCmw
  • 你能把你的代码放在stackblitz.com上吗?在线代码编辑器?
  • @Umbro。您可以通过以下链接访问 GitHub repo 中的源代码:github.com/mohammadoftadeh/simple-react-socket-io
  • 但是您在 Github 中的文件 client 没有配置
【解决方案2】:

REACT_APP_API 环境变量从 http://localhost:8000/api 更改为 http://localhost:8000,即删除 /api

【讨论】:

  • 它不起作用。我使用 url 在浏览器中运行应用程序:localhost:3000,服务器端口 8000.. 也许我在env 中的变量我应该更改为;来自localhost:3000 的 REACT_APP_API 环境变量??
  • 虽然我使用的是 socket-io 版本 4,但在此更改之后,我的系统上运行您的代码没有任何问题。我会检查您的版本。同时,您能否从网络选项卡中附加您的请求标头的 SS。任何以/socket.io/?开头的请求的请求标头。
  • 与您的版本相同,没有问题。您能否附上您的网络请求的屏幕截图。这会给我一些关于这个问题的线索。
  • 你能不能把socket.current = io(process.env.REACT_APP_API);改成socket.current = io("http://localhost:8000");
  • 已更新。我添加了请求标头
【解决方案3】:

使用 http 包。

const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);

io.on('connection', socket => {
    ....
});

server.listen(3000, () => {
    ....
});

【讨论】:

  • 我做到了,但我仍然无法在终端中看到结果
  • 如果您在“socket.on”行之前使用console.log,您会得到确认的连接吗?
  • 我是这样做的:io.on('connection', function(data) { console.log('new client connected'); }); 我可以在终端中看到“新客户端已连接”
  • 是的,我可以在socket.on之前看到console.log('new client connected');
猜你喜欢
  • 1970-01-01
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 2020-06-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-25
相关资源
最近更新 更多