【发布时间】: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