我在node.js,socket.io和mongoose中构建聊天应用程序。我的目标是建立一对一聊天,它类似于facebook网络聊天。因此,基本上每当我点击一个用户时,它就会转到该用户网址并可能与他/她聊天
但我面临的问题是,我只能向目标用户发送消息,而不是发给我自己。
这是当前的代码
了Serverside
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天,请有人结束这种苦难:(
答案 0 :(得分: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' });
}
});
});
答案 1 :(得分:-1)
这有点难以回答,因为感觉你实际上是在问错误的问题。要了解你是如何"假设"要做到这一点,你必须先解决其他一些架构问题。
您需要解决的首要问题是身份验证/授权问题,即当您将套接字从浏览器连接到服务器时,您的服务器如何知道您是谁并且知道您是谁?不是冒名顶替者吗?我没有这方面的最佳做法,但您可能想查看可能会给您一些想法的socketio-auth package。
您需要解决的第二件事是如何将经过身份验证的用户与套接字相关联。我能找到的唯一可以参考的来源是socket.io网站上的chat demo。
此时,您的服务器中应该有一组具有关联用户的套接字。当蝙蝠侠上线时,您应该检查数据库中是否有他参与的任何聊天,并让他通过ID连接到该聊天室:
Chat.find({usernames: "Batman"}).exec().then(function(chats){
chats.forEach(function(chat){
socket.join(chat.id);
})
});
所以到目前为止,假设Joker还没有与蝙蝠侠建立聊天,因此数据库中没有连接它们的聊天。
当小丑想和蝙蝠侠聊天时,你需要发送一个" connect"
中的套接字消息示例:
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');
});
});
现在刷一下很多的详细信息,每个细节都取决于您的应用程序架构。此外,我的语法可能有些偏差,这些示例仅作为您应该尝试的指示,而不是作为您问题的直接解决方案。