【问题标题】:Why can I not save the current room in Socket.IO?为什么我无法在 Socket.IO 中保存当前房间?
【发布时间】:2016-12-23 03:53:12
【问题描述】:

这几天我一直在摆弄socket.io,遇到了这个问题。在我的 server.js 中更新 currentRoom 变量后,socket 仍然引用第一个房间集,在这种情况下,默认房间是“General”。

当套接字离开旧房间加入新房间时,发送的消息不会按预期发送到新房间,而是发送到旧房间,即使当前房间存储在变量中并且是用作定位插座房间的方法。

我的 server.js:

const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const socketIo = require('socket.io');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackConfig = require('./webpack.config');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

app.use(express.static(__dirname + '/public'));
app.use(webpackDevMiddleware(webpack(webpackConfig)));
app.use(bodyParser.urlencoded({ extended: false }));

io.on('connection', socket => {
  var rooms = ['General'];
  var currentRoom;
  const defaultRoom = 'General';

  socket.join('General');
  currentRoom = "General";

  //socket.emit('setup', { rooms:rooms, currentRoom: currentRoom });

  socket.on('new room', room => {
    socket.leave(currentRoom)
    currentRoom = room;
    socket.join(currentRoom);
    socket.emit('new room', room);
    console.log("New room has been created called: " + currentRoom);
  })

  socket.on('message', body => {
    console.log("Sending message to current room: " + currentRoom);
    socket.to(currentRoom).emit('message', {
      body,
      from: socket.id.slice(8)
    })
  })
})

server.listen(3000);

在前端我有这个反应组件 info.js:

import React from 'react';
import io from 'socket.io-client';

import Room from './Room';
import RoomList from './RoomList';
import User from './User';
import UserList from './UserList';

export default class Info extends React.Component {
  constructor(){
    super();
    this.state = {
      users: [],
      rooms: [],
      currentRoom: ''
    }
  }

  componentDidMount(){
    this.socket = io('/');
    //set defaults for room list
    this.socket.on('setup', data => {
      this.setState({ rooms: [...this.state.rooms, data.rooms] });
      this.setState({ currentRoom: data.currentRoom });
    })
    this.socket.on('new room', room => {
      this.setState({ currentRoom: room });
    })
  }

  userSubmit = event => {
    const username = event.target.value
    if(event.keyCode === 13  && username){
      this.setState({ users: [...this.state.users, username] });
      this.socket.emit('new user', username)
      event.target.value = '';
    }
  }

  roomSubmit = event => {
    const room = event.target.value
    if(event.keyCode === 13  && room){
      this.setState({ rooms: [...this.state.rooms, room] });
      this.socket.emit('new room', room)
      event.target.value = '';
    }
  }

  render(){
    const rooms = this.state.rooms.map((room, index) => {
      return <li key={index}>{room}</li>
    })

    const users = this.state.users.map((user, index) => {
      return <li key={index}>{user}</li>
    })
    return(
      <div class="chat-info">
        <RoomList rooms={rooms}/>
        <Room roomSubmit={this.roomSubmit}/>

        <UserList users={users}/>
        <User userSubmit={this.userSubmit}/>
        <p>Current Room: {this.state.currentRoom}</p>
      </div>
    )
  }
}

当我通过“新房间”事件更改房间时,当前房间确实得到更新,并且套接字似乎加入了新房间;但是,当套接字随后使用“消息”事件向当前房间发送消息时,套接字的消息将被发送到默认房间“常规”。为什么会这样?我是 Socket.IO 的新手,所以我可能没有看到一些明显的东西。任何帮助,将不胜感激。干杯!

编辑:从新房间和消息事件的服务器 js 中的 console.log 进入我的终端:

New room has been created called: new //new refers to the value of currentRoom
Sending message to current room: General //General refers to the value of currentRoom

这些终端消息是在我在客户端上创建了一个新房间并尝试在创建并加入该新房间后发送一条消息之后出现的。如您所见,我创建并加入了一个简单称为“new”的新房间,但是当我现在尝试向 currentRoom 发送消息时,该消息被发送到“General”房间。

Edit#2:这是我在 server.js 文件上运行的调试日志。

      express:router dispatching GET /bundle.js +56ms
      express:router query  : /bundle.js +0ms
      express:router expressInit  : /bundle.js +1ms
      express:router serveStatic  : /bundle.js +0ms
      send stat "/Users/alexwerner/Desktop/development/Web Development/rooms.io/public/bundle.js" +0ms
      express:router webpackDevMiddleware  : /bundle.js +1ms
      engine intercepting request for path "/socket.io/" +149ms
      engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogAC" +0ms
      engine handshaking client "wlJpbWQIxMnTHrEYAAAA" +2ms
      engine:socket sending packet "open" ({"sid":"wlJpbWQIxMnTHrEYAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000})
+1ms
      engine:polling setting request +1ms
      engine:socket flushing buffer to transport +0ms
      engine:polling writing "      �0{"sid":"wlJpbWQIxMnTHrEYAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}"
+3ms
      engine:socket executing batch send callback +1ms
      socket.io:server incoming connection with id wlJpbWQIxMnTHrEYAAAA +0ms
      socket.io:client connecting to namespace / +1ms
      socket.io:namespace adding socket to nsp / +0ms
      socket.io:socket socket connected - writing packet +1ms
      socket.io:socket joining room /#wlJpbWQIxMnTHrEYAAAA +0ms
      socket.io:client writing packet {"type":0,"nsp":"/"} +0ms
      socket.io-parser encoding packet {"type":0,"nsp":"/"} +1ms
      socket.io-parser encoded {"type":0,"nsp":"/"} as 0 +0ms
      engine:socket sending packet "message" (0) +0ms
      socket.io:socket joining room General +1ms
      socket.io:socket joined room /#wlJpbWQIxMnTHrEYAAAA +0ms
      socket.io:socket joined room General +0ms
      engine intercepting request for path "/socket.io/" +1ms
      engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogAJ" +0ms
      engine handshaking client "Mh_obCHm_rGKbN2NAAAB" +1ms
      engine:socket sending packet "open" ({"sid":"Mh_obCHm_rGKbN2NAAAB","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000})
+0ms
      engine:polling setting request +0ms
      engine:socket flushing buffer to transport +0ms
      engine:polling writing "      �0{"sid":"Mh_obCHm_rGKbN2NAAAB","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}"
+1ms
      engine:socket executing batch send callback +0ms
      socket.io:server incoming connection with id Mh_obCHm_rGKbN2NAAAB +0ms
      socket.io:client connecting to namespace / +1ms
      socket.io:namespace adding socket to nsp / +0ms
      socket.io:socket socket connected - writing packet +0ms
      socket.io:socket joining room /#Mh_obCHm_rGKbN2NAAAB +0ms
      socket.io:client writing packet {"type":0,"nsp":"/"} +0ms
      socket.io-parser encoding packet {"type":0,"nsp":"/"} +0ms
      socket.io-parser encoded {"type":0,"nsp":"/"} as 0 +0ms
      engine:socket sending packet "message" (0) +1ms
      socket.io:socket joining room General +0ms
      socket.io:socket joined room /#Mh_obCHm_rGKbN2NAAAB +0ms
      socket.io:socket joined room General +0ms
      engine upgrading existing transport +40ms
      engine:socket might upgrade socket transport from "polling" to "websocket" +1ms
      engine intercepting request for path "/socket.io/" +4ms
      engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogB2&sid=wlJpbWQIxMnTHrEYAAAA"
+0ms
      engine setting new request for existing client +0ms
      engine:polling setting request +0ms
      engine:socket flushing buffer to transport +0ms
      engine:polling writing "�40" +1ms
      engine:socket executing batch send callback +0ms
      engine intercepting request for path "/socket.io/" +0ms
      engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogB4&sid=Mh_obCHm_rGKbN2NAAAB"
+0ms
      engine setting new request for existing client +0ms
      engine:polling setting request +0ms
      engine:socket flushing buffer to transport +0ms

请注意,这里创建了两个套接字;但是,我一次只在一个浏览器上打开了该应用程序。我不确定这是否是 socket.io 的工作方式,或者这是否是我的问题。

事件日志:

socket.io-parser decoded 2["new room","New Room"] as {"type":2,"nsp":"/","data":["new room","New Room"]} +0ms
  socket.io:socket got packet {"type":2,"nsp":"/","data":["new room","New Room"]} +0ms
  socket.io:socket emitting event ["new room","New Room"] +0ms
  socket.io:socket leave room General +0ms
  socket.io:socket joining room New Room +0ms
  socket.io:client writing packet {"type":2,"data":["new room","New Room"],"nsp":"/"} +0ms
  socket.io-parser encoding packet {"type":2,"data":["new room","New Room"],"nsp":"/"} +0ms
  socket.io-parser encoded {"type":2,"data":["new room","New Room"],"nsp":"/"} as 2["new room","New Room"] +0ms
  engine:socket sending packet "message" (2["new room","New Room"]) +0ms
  engine:socket flushing buffer to transport +0ms
  engine:ws writing "42["new room","New Room"]" +1ms
New room has been created called: New Room
  socket.io:socket left room General +0ms
  socket.io:socket joined room New Room +0ms
  engine:ws received "42["message","Test Post"]" +11s
  engine:socket packet +1ms
  socket.io-parser decoded 2["message","Test Post"] as {"type":2,"nsp":"/","data":["message","Test Post"]} +0ms
  socket.io:socket got packet {"type":2,"nsp":"/","data":["message","Test Post"]} +0ms
  socket.io:socket emitting event ["message","Test Post"] +0ms
Sending message to current room: General
  socket.io-parser encoding packet {"type":2,"data":["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}],"nsp":"/"} +14.8m
  socket.io-parser encoded {"type":2,"data":["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}],"nsp":"/"} as 2["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}] +0ms
  socket.io:client writing packet ["2[\"message\",{\"body\":\"Test Post\",\"from\":\"aDw0sZU_XZAAAE\"}]"] +0ms
  engine:socket sending packet "message" (2["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]) +0ms
  engine:socket flushing buffer to transport +0ms
  engine:ws writing "42["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]" +0ms
  socket.io:client writing packet ["2[\"message\",{\"body\":\"Test Post\",\"from\":\"aDw0sZU_XZAAAE\"}]"] +1ms
  engine:socket sending packet "message" (2["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]) +0ms
  engine:socket flushing buffer to transport +0ms
  engine:ws writing "42["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]" +0ms
  engine:ws received "2" +4s
  engine:socket packet +0ms
  engine:socket got ping +0ms
  engine:socket sending packet "pong" (undefined) +0ms
  engine:socket flushing buffer to transport +0ms
  engine:ws writing "3" +0ms
  engine:ws received "2" +0ms
  engine:socket packet +1ms
  engine:socket got ping +0ms
  engine:socket sending packet "pong" (undefined) +0ms
  engine:socket flushing buffer to transport +0ms
  engine:ws writing "3" +0ms
  engine:ws received "2" +3s
  engine:socket packet +0ms
  engine:socket got ping +0ms
  engine:socket sending packet "pong" (undefined) +0ms
  engine:socket flushing buffer to transport +0ms
  engine:ws writing "3" +0ms
  engine:ws received "2" +1ms
  engine:socket packet +0ms
  engine:socket got ping +0ms
  engine:socket sending packet "pong" (undefined) +0ms
  engine:socket flushing buffer to transport +0ms

【问题讨论】:

  • 你认为它为什么会被发送到General 房间?你有什么证据?您是否意识到一个套接字可以同时连接到多个房间,所以当您先将其连接到General 然后再连接到新房间时,套接字仍在General 房间中。你没有leave那个房间,所以它还在那个房间里。
  • @jfriend00 -- 我更新了代码以显示我从服务器文件中获取的日志,并且我还将套接字设置为在创建新房间时离开当前房间。我相信,但可能是错误的,消息正在发送到 General 房间,因为在 message 事件中,我发送了一个日志,我相信它会告诉我消息发送时 currentRoom 的名称发送。当 currentRoom 在 new room 事件下发生变化时,message 事件仍然使用在 socket 连接时设置的默认 General room。
  • 您是否意识到在您的代码中currentRoom 对于每个套接字都是唯一的?您的服务器上不只有一个currentRoom,但每个套接字都有自己的currentRoom 变量?因此,如果其他一些套接字发送new room,那将仅更改该特定套接字的currentRoom。您可以逻辑地将其视为服务器端套接字对象的属性,就好像它是socket.currentRoom。因此,当一个套接字发送message 时,该消息将被发送到发送套接字的currentRoom,而不是其他一些套接字设置的最后一个currentRoom。
  • 另外,你说你更新了代码以显示你得到的日志,但我在你的问题中根本看不到任何日志。如果您显示客户端代码并准确显示客户端代码所看到的内容,这也可能会有所帮助。我仍然不知道您为什么认为消息被发送到错误的房间。你还没有解释你为什么这么认为。是否涉及多个客户,General 房间中的某些客户正在收到一条只应该用于其他房间的消息?如果有,请详细说明。我们可以帮助您,但前提是您向我们提供更多信息。
  • 客户端中的roomSubmit()是否有可能被表单中的提交按钮调用?并且,该提交按钮是否会导致您的页面重新加载,因为默认情况下,提交按钮会执行表单发布,如果没有实际提交的表单会重新加载页面,从而创建一个新的、从头开始的 socket.io 连接,当然,在General 房间里,就像所有新的插座一样?如果您在 io.on('connection', ...) 代码中添加 console.log() 语句,您可以更清楚地看到这一点,这样您就可以看到所有新连接都被记录了。

标签: javascript node.js sockets express socket.io


【解决方案1】:

在意识到创建时有两个套接字之后,我意识到我的问题出在那段代码的某个地方。原来我没有在我的反应项目中正确嵌套 Socket.IO。我有多个实例,其中组件在客户端上导入 socket.io。

(我在不止一个组件中有这一行):

import io from 'socket.io-client';

事实证明,如果在项目中多次使用此导入,则会创建多个套接字。 (这是有道理的,不幸的是我花了这么长时间才发现我的错误)。

如果有人在使用 React 框架时创建多个套接字时遇到问题,该解决方案很容易实现。首先,删除组件上的 socket.io 导入,并将语句移动到父组件。就我而言,这是我的布局组件。

Layout.js

import React from 'react';
import io from 'socket.io-client';

import Chat from './Chat/Chat';
import Info from './Info/Info';

const socket = io();

export default class Layout extends React.Component {
  render(){
    return(
      <div class="wrapper">
        <h1>Rooms.io!</h1>
        <Chat socket={socket}/>
        <Info socket={socket}/>
      </div>
    )
  }
}

现在 import 语句位于父组件中。您可以将套接字从父组件传递给任何子组件。如您所见,我将套接字传递给两个组件 Chat 和 Info。

在这些子组件中,您可以像对待 React 中的任何其他类型的 prop 一样对待套接字。在我的示例中,目前,我将套接字变量设置为等于套接字属性,(如我的 componentDidMount 函数中所示)。

聊天.js

import React from 'react';

import Message from './Message';
import MessageList from './MessageList';

export default class Chat extends React.Component {
  constructor(){
    super();
    this.state = { messages: [] };
  }

  componentDidMount(){
    const socket = this.props.socket;
    socket.on('message', message => {
      this.setState({ messages: [...this.state.messages, message] });
    })
  }

  handleSubmit = event => {
    const socket = this.props.socket;
    const body = event.target.value
    if(event.keyCode === 13  && body){
      const message = {
        body,
        from: 'Me'
      }
      this.setState({ messages: [...this.state.messages, message] });
      socket.emit('message', body)
      event.target.value = '';
    }
  }

  render(){
    const messages = this.state.messages.map((message, index) => {
      return <li key={index}>{message.from}: {message.body}</li>
    })
    return(
      <div class="chat">
        <MessageList messages={messages}/>
        <Message handleSubmit={this.handleSubmit}/>
      </div>
    )
  }
}

感谢@jfriend00 的帮助;我希望任何阅读这篇文章的人都有美好的一天,并且永远不会忘记在 React 中正确地嵌套他们的套接字。干杯!

【讨论】:

    猜你喜欢
    • 2017-11-06
    • 2018-02-01
    • 2013-10-03
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多