我希望服务器仅在客户端在另一个套接字上发送消息后才开始侦听来自客户端的某个套接字。我试着这样编写我的代码:
socket.on('listentome', function() {
socket.on('actualmessage', function() {
...
});
});然而,它并没有起作用。有什么建议吗?
发布于 2018-07-12 03:17:48
最简单的解决方案是保持状态,这会让你知道你是否在等待第二个事件。
let waiting = false;
socket.on('listentome', () => waiting = true);
socket.on('actualmessage', () => {
if (!waiting) return; // if we're not waiting for this event, ignore it
waiting = false;
...
});发布于 2018-07-12 17:09:37
我让一切都运行得很顺利,这是我的代码。注意,playerMovementListener函数安装了8个socket.on-s,这些socket.on-s只监听该玩家,因为玩家发送他们的ID和他们的动作。
io.on('connection', function(socket) {
//generate a user ID//
var userID = makeID();
//check if user is trying to connect from the same IP... if so send them out//
for(var i = 0; i < users.length; i++) {
if(users[i].IP == socket.handshake.address) {
io.sockets.emit(socket.id, 'You can only play one instance of the game!');
return;
}
}
//send the user's ID to the user//
io.sockets.emit(socket.id, userID);
//add the users to the array of connected users//
users.push({
'IP' : socket.handshake.address,
'ID' : userID,
});
//if user queues up for game (they send their ID when they queue up)...
//it is wise to check if their ID exists in the list of connected users to avoid DDOS, but I haven't implemented that yet
socket.on('queueup', function(data) {
//if there are already users playing...
if(pairs.length > 0) {
//get the index of the last pair...
var pairIndex = pairs.length-1;
if(pairs[pairIndex].length < 2) {
//if pair is not full (means that other user is queued and waiting for opponent), add the user to the pair and start the game//
pairs[pairIndex].push({
'ID' : data,
'x' : 850,
'y' : 850,
'mx' : 0,
'my' : 0,
'vermove' : 0,
'hormove' : 0,
});
//add the listener for this user...
playerMovementListener(socket, pairs[pairIndex][1].ID, pairIndex, 1);
//update and send coordinates 60 times per second..
setInterval(function() { runGame(pairs[pairIndex][0], pairs[pairIndex][1], pairIndex); }, 1000/60);
//send the ready message to the users in the pair..
io.sockets.emit(pairs[pairIndex][0].ID + ' ready', 'go');
io.sockets.emit(pairs[pairIndex][1].ID + ' ready', 'go');
} else {
//however if pair is already full, create new pair, add user to it, add listener for user and wait for opponent...
var pair = [];
pair.push({
'ID' : data,
'x' : 150,
'y' : 150,
'mx' : 0,
'my' : 0,
'vermove' : 0,
'hormove' : 0,
})
pairs.push(pair);
playerMovementListener(socket, pairs[pairIndex+1][0].ID, pairIndex+1, 0);
}
} else {
//if no users are playing, add user to first pair, add listener and wait for opponent...
var pair = [];
pair.push({
'ID' : data,
'x' : 150,
'y' : 150,
'mx' : 0,
'my' : 0,
'vermove' : 0,
'hormove' : 0,
});
pairs.push(pair);
playerMovementListener(socket, pairs[0][0].ID, 0, 0);
}
});
});这段代码按预期工作。此时,我只需要删除侦听器&每当玩家断开连接或离开游戏时,清除游戏功能的间隔。
不起作用的是试图在第二个玩家连接之后安装两个玩家的侦听器(而不是在第一个玩家连接之后安装第一个的侦听器,即使他们还没有在游戏中……这是有效的)。我甚至不确定为什么,但重点是我让它工作了。
发布于 2018-07-12 09:25:08
因此,您提出的设计:
socket.on('listentome', function() {
socket.on('actualmessage', function() {
...
});
});确实只是一个糟糕的设计,充满了问题。以下是一些问题:
listentome消息时,您都会为actualmessage添加另一个事件处理程序,除非您在它们触发后将其删除,否则它们会累积起来,并且您将多次处理每个接收到的actualmessage。listentome和actualmessage序列在运行,你不知道哪个actualmessage消息属于哪个listentome第一个消息,上面前两个问题的任何解决方案都可能会加倍处理第一个到达的消息,而根本不处理第二个消息。因此,如果同时有多个listentome序列在运行(这本质上是一个并发问题),这种体系结构就根本不起作用。那么,如何解决这个问题呢?你没有给我们很多你试图解决的实际问题的背景,让我们帮助你重新架构它,但我会尽可能多地给你提供想法。
首先,在事件驱动的体系结构中,您通常希望安装一次事件处理程序,以便它们始终处于适当的位置。然后,您可以使用state来决定在消息到达时如何处理该消息。
其次,您不希望为了执行某些操作而在服务器上完全不需要请求之间的状态。因此,您更希望发送的任何请求都是完全独立完成的,这样您就不需要一系列事件来完成某项任务。作为类比,使用http POST,您不会在单独的请求中一次发送表单的每个字段,然后以某种方式告诉服务器您已经完成,并让它处理所有事情。相反,您收集了需要发送的所有内容,并将其发送到一个http POST中,服务器处理所有内容并发送一个响应。一切都是无状态的,而且要简单得多。
我正在创建一个多人游戏,用户可以成对地玩。服务器为每个用户分配一个唯一的ID,然后将其发送给每个套接字发送,并必须将其包含到每个套接字发射中以进行验证(以避免黑客攻击)。当用户排队时,他们发送一个消息(第一个socket.on),其中包含他们的ID,等等。当他们与用户配对时(如果用户已经在等待,就会立即发生这种情况,因此是嵌套的socket.on),他们必须被发送到游戏中,只有那时我才能启动侦听器,了解玩家的移动,等等(第二个socket.on)。
你没有向我们展示你的实际代码,但它可能会更简单,只需要在socket上添加各种监听器,用于玩家的移动,等等……当用户第一次连接并且只让每个处理程序在处理程序开始时调用一个公共函数,该函数检查套接字在游戏中是否有效连接。如果没有,什么也不做。如果是,则处理该消息。然后,您可以在第一次连接套接字时安装所有事件处理程序一次。
您甚至可以对其进行抽象:
socket.onWhenInGame('someGameMessage', function(data) {
// this will only get called when connected in a game
});并且,该方法的实现如下所示:
socket.onWhenInGame = function(msg, fn) {
return socket.on('msg', function(data) {
if (!this.inGame) {
// not in a game, ignore this message
return;
} else {
fn(msg, data);
}
});
};然后,每当您将套接字加入游戏或从游戏中删除套接字时,您只需维护socket.inGame标志。而且,您可以只使用socket.onWhenInGame()进行编程,而不必担心所有上述问题。
https://stackoverflow.com/questions/51292563
复制相似问题