如何生成房间 ID 并强制两个用户加入该房间?
Posted
技术标签:
【中文标题】如何生成房间 ID 并强制两个用户加入该房间?【英文标题】:How to generate a room id and force two users to join that room? 【发布时间】:2016-05-07 09:42:01 【问题描述】:我正在用 node.js、socket.io 和 mongoose 构建一个聊天应用程序。我的目标是建立一对一的聊天,它类似于 facebook 网络聊天。所以基本上每当我点击一个用户时,它都会转到该用户的网址并可能与他/她聊天
但我面临的问题是我只能将消息发送给目标用户,而不能发送给我自己。
这是当前代码
服务器端
socket.on('chatTo', function(data)
User.findOne( username: data.destinationUsername, socketId: '$ne': null, function(err, foundUser)
if (foundUser)
io.to(foundUser.socketId).emit('incomingChat', sender: user.username, message: data.message );
else
io.to(socket.id).emit('deliverError', error: foundUser + ' is not online' );
);
);
客户端
$(function()
var socket = io();
function chatTo(message, destinationUsername)
socket.emit('chatTo', message: message, destinationUsername );
$('#sendMessage').submit(function()
var input = $('#message').val();
var username = $('#username').val();
chatTo(input, username);
$('#message').val('');
return false;
);
socket.on('incomingChat', function(data)
var html = data; // Messages to append to media-list
$('.media-list').append(html);
);
);
所以这里发生的是,在客户端,用户 A 点击表单提交,提交消息,它将调用 chatTo
函数并发出数据。只是想让你们知道,input
和 username
来自 html 页面。它看起来像这样
input = "Hello";
username = "jackmoscovi" // user's username
然后它会将这两个数据发送回服务器,socket.on('chatTo')
正在监听。在一些 MongoDB 操作之后,如果找到用户,则向该特定套接字发出。
结果是
蝙蝠侠发出的信息只显示在小丑的页面上,而不会出现在蝙蝠侠的页面上。我知道这一点,因为我专门向那个套接字发射。真正的问题是我如何强制这两个用户都在一个独特的房间里?我应该创建一个新的Room mongoose model
吗?然后拨打socket.join('uniqueRoom')
?
然后简单地io.to('uniqueRoom').emit("Message?");
我将如何实现这个房间机制?
我已经挣扎了2天了,请有人结束这种痛苦:(
【问题讨论】:
如果您的问题是如何向发射器发送事件,则可以在回调函数中执行this.emit(......)
@AlexBlex 有可能我需要将房间存储在猫鼬中,因此使用 mongodb 标签:)
【参考方案1】:
首先创建一个像这样的猫鼬模式
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var messageSchema=new Schema(
sender :
type : String,
,
receiver :
type : String.
,
message :
type : String
)
mongoose.model('messages',messageSchema);
然后在服务器代码中
message = mongoose.model('messages')
socket.on('chatTo', function(data) // data is json containing sender, receiver and message
User.findOne( username: data.destinationUsername, socketId: '$ne': null, function(err, foundUser)
if (foundUser)
io.to(foundUser.socketId).emit('incomingChat', sender: user.username, message: data.message );
socket.emit('incomingChat', sender: user.username, message: data.message );
var newMessage = new message(
sender : data.sender,
receiver : data.receiver,
message : data.message
)
newMessage.save(function (err, data)
if(err)
console.log(err)
)
else
io.to(socket.id).emit('deliverError', error: foundUser + ' is not online' );
);
);
【讨论】:
这种方法的问题是,我需要将消息保存到一个房间。这样以后渲染数据会更容易。 你可以简单地创建一个猫鼬消息模式,其中包含发送者、接收者和消息的唯一用户名。导致结构类似::: var messageSchema = new mongoose.Schema("sender":String, "receiver":String, "message"); var messageSchema = new mongoose.Schema("sender":String, "receiver":String, "message":String);因此,当您想从数据库中获取消息时,您可以使用发送者和接收者字段来查询它们。由于它是一对一聊天,我看不出创建房间的意义 感谢您的回答,但我刚刚意识到还有一个问题。在渲染消息模型中的数据时,我将如何渲染它? 对不起,如果我没有得到你。当你说渲染时,你到底是什么意思?【参考方案2】:这有点难以回答,因为感觉你实际上是在问错误的问题。要了解您“应该”如何做到这一点,您实际上必须首先解决很多其他架构问题。
您需要解决的第一件事是身份验证/授权问题,即当您将套接字从浏览器连接到服务器时,您的服务器如何知道您是谁并且知道您不是冒名顶替者?我没有这方面的最佳实践,但您可能想查看socketio-auth package,这可能会给您一些想法。
您需要解决的第二件事是如何将经过身份验证的用户与套接字关联。我能找到的唯一参考来源是 socket.io 网站上的chat demo。
此时,您的服务器中应该有一组具有关联用户的套接字。当蝙蝠侠上线时,您应该检查数据库中是否有他参与的任何聊天,并让他通过 id 连接到该聊天室:
Chat.find(usernames: "Batman").exec().then(function(chats)
chats.forEach(function(chat)
socket.join(chat.id);
)
);
到目前为止,这是假设小丑尚未创建与蝙蝠侠的聊天,因此数据库中没有将两者连接起来的聊天。
当小丑想和蝙蝠侠聊天时,你需要通过套接字发送一个“连接”消息
-
在其中创建与他们两人的聊天
如果它们当前已连接到服务器,则查找它们当前的套接字,并且
发送他们已相互连接的消息
示例:
socket.on('startChat', function(data)
//assuming that you have assocated the current user with the socket
var currentUser = socket.user;
//who the current user (Joker) wants to connect to
var connectToUser = data.connectToUser; // Batman
Chat.create(
usernames: [currentUser.username, connectToUser.username] // ["Joker", "Batman"]
).then(function(newChat)
socket.join(newChat.id); // add current user (Joker) to that socket.io room
// this is overly simplified: assuming you have an array collectionOfConnectedSockets which
// contains all currently connected sockets
var otherUserSocket = collectionOfConnectedSockets[connectToUser.username];
//otherUserSocket now is Batman's socket - so make him join the room
otherUserSocket.join(newChat.id);
//send them both a message that a chat has been connected
io.to(newChat.id).emit('You have been connected to a new chat');
);
);
现在,这会覆盖 很多 的细节,而这些细节中的每一个都取决于您的应用程序的架构。此外,我的语法可能有点偏离,这些示例仅作为您应该尝试做的指示,而不是作为您问题的直接解决方案。
【讨论】:
以上是关于如何生成房间 ID 并强制两个用户加入该房间?的主要内容,如果未能解决你的问题,请参考以下文章