我正在尝试创建一个聊天系统,用户可以向所有人发送消息(此消息显示在id为“chat”的div中)并且我已经实现了此功能。现在我想实现私聊。用户可以点击右栏上的另一个用户名(显示所有登录用户),一旦他点击用户名,就会出现一个小窗口(div为“chatpopup”类),在这个窗口中有一个提交按钮和一个输入要填写的消息文本,一旦点击提交按钮,该消息应该发送给其他用户。
这就是我所拥有的,如果我点击一个用户(在屏幕的右侧),会显示一个小窗口(chatpopup)但是当我尝试在这个小窗口内提交表单时,应用程序崩溃了。 我还想收到关于建立私人聊天的一些提示,例如我如何在用户的客户端打开一个应该接收消息的新窗口(带有消息接收)?
的index.html
<html>
<head>
<title>Chat with socket.io and node.js</title>
<style>
#contentWrap
{
width:100%;
display: none;
}
#chatWrap {float: left; width:80%;}
#chat
{
height:500px;
width:96%;
border: 1px #000 solid;
padding-left:2%;
padding-right:2%;
}
#users
{
margin-left:82%; width:15%;
height:500px;
border: 1px #000 solid;
text-align:right;
}
#send-message {margin-top:3%; width:100%;}
#message {width:80%;}
.err1r{ padding-top:1%;
color: red;
}
.whisper{
color: gray;
font-style: italic;
}
p.sideusername:nth-child(even) {background-color:#FAFAFA; padding-bottom:5%; padding-top:5%;}
p.sideusername:nth-child(odd) {background-color: #f5f5f0; padding-bottom:5%; padding-top:5%;}
.chatpopup {width:350px; height: 250px; background-color:blue;}
#interlocutore {background-color:red; height: 30px; text-align: left;}
#msgspace {height:150px; background-color:yellow;}
</style>
</head>
<body>
<div id="nickWrap">
<p>Enter a username:</p>
<p id="nickError"></p>
<form id="setNick">
<input size="35" id="nickname"></input>
<input type="submit"></input>
</form>
</div>
<div id="contentWrap">
<div id="chatWrap">
<div id="chat"></div>
<form id="send-message">
<input size="35" id="message"></input>
<input type="submit"></input>
</form>
</div>
<div id="users"></div>
</div>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
jQuery(function($){
var socket = io.connect();
var $nickForm = $('#setNick');
var $nickError = $('#nickError');
var $nickBox = $('#nickname');
var $users = $('#users');
var $messageForm = $('#send-message');
var $messageFormPopup = $('#send-message-popup');
var $messageBox = $('#message');
var $messageBoxPopup = $('#messagePopup');
var $chat = $('#chat');
$nickForm.submit(function(e){
e.preventDefault();
socket.emit('new user', $nickBox.val(), function(data){
if(data){
$('#nickWrap').hide();
$('#contentWrap').show();
} else{
$nickError.html('That username is already taken! Try again.');
}
});
$nickBox.val('');
});
socket.on('usernames', function(data){
$users.empty();
for(var i=0; i < data.length; i++){
$users.append('<p class="sideusername">' + data[i] + "</p>");
}
});
$messageForm.submit(function(e)
{
e.preventDefault();
socket.emit('send message', $messageBox.val(), function(data)
{
});
$chat.append('<span class="error">' + data + "</span><br/>");
$messageBox.val('');
});
$messageFormPopup.submit(function(e)
{
e.preventDefault();
socket.emit('send popup message', $messageBoxPopup.val(), function(dataPopup)
{
});
$messageBoxPopup.val('');
});
socket.on('load old msgs', function(docs){
for(var i=docs.length-1; i >= 0; i--){
displayMsg(docs[i]);
}
});
socket.on('new message', function(data){
displayMsg(data);
});
function displayMsg(data){
$chat.append('<span class="msg"><b>' + data.nick + ': </b>' + data.msg + "</span><br/>");
}
socket.on('whisper', function(data){
$chat.append('<span class="whisper"><b>' + data.nick + ': </b>' + data.msg + "</span><br/>");
});
$(document).on("click", ".closepopup", function() {
$(this).parents('.chatpopup').hide();
});
$(document).on("click", ".sideusername", function()
{
var interlocutore = $(this).text();
$chat.append('<div class="chatpopup"><table><tr><td id="interlocutore"></td><td><p class="closepopup">X</p></td></tr><tr><td colspan="2" id="msgspace"></td></tr><tr><td colspan="2"><form id="send-message-popup"> <input size="35" id="messagePopup"></input><input type="submit"></input></form></td></tr></table></div>');
$('#interlocutore').append(interlocutore);
});
});
</script>
</body>
</html>
app.js
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
mongoose = require('mongoose'),
users = {};
server.listen(3000);
mongoose.connect('mongodb://localhost/chat', function(err)
{
if(err)
console.log(err);
else console.log('Connected to mongodb!');
});
var chatSchema = mongoose.Schema(
{
nick: String,
msg: String,
created: {type: Date, default: Date.now}
});
var Chat = mongoose.model('Message', chatSchema);
app.get('/', function(req, res)
{
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket)
{
var query = Chat.find({});
query.sort('-created').limit(8).exec(function(err, docs)
{ // carico gli ultimi 8 messaggi in ordine di data
if(err) throw err;
socket.emit('load old msgs', docs);
});
socket.on('new user', function(data, callback)
{
if (data in users)
callback(false);
else
{
callback(true);
socket.nickname = data;
users[socket.nickname] = socket;
updateNicknames();
}
});
function updateNicknames()
{
io.sockets.emit('usernames', Object.keys(users));
}
socket.on('send message', function(data, callback)
{
var msg = data.trim();
var newMsg = new Chat({msg: msg, nick: socket.nickname});
newMsg.save(function(err)
{
if(err) throw err;
io.sockets.emit('new message', {msg: msg, nick: socket.nickname});
});
socket.on('disconnect', function(data)
{
if(!socket.nickname) return;
delete users[socket.nickname];
updateNicknames();
});
});
socket.on('send popup message', function(data, callback)
{
/*var msgPopup = dataPopup.trim();
if (msgPopup !== "")
users[interlocutore].emit('whisper', {msg: msgPopup, nick: socket.nickname});
*/
var msg = data.trim()+" hello";
var newMsg = new Chat({msg: msg, nick: socket.nickname});
newMsg.save(function(err)
{
if(err) throw err;
io.sockets.emit('new message', {msg: msg, nick: socket.nickname});
});
socket.on('disconnect', function(data)
{
if(!socket.nickname) return;
delete users[socket.nickname];
updateNicknames();
});
});
});
答案 0 :(得分:2)
要使用socket.IO创建私人聊天,您首先需要了解socket.IO中个房间的工作方式。你可以找到大量的教程。您还可以查看this帖子以获取帮助。
现在您需要扩展此功能以创建私人聊天系统。为此,您需要为每个已连接或联机的客户端提供唯一的 id 。 socket.id 是每个客户在加入聊天时获得的唯一键。
在客户端,您可以向服务器发送名称以及消息。你这样做:
socket.emit('privateMessage', 'theUserName', message);
在服务器端,您可以管理已连接的用户数组,并保存其唯一的用户名或 ID 。
var connectedClients = {};
因此,每当用户连接到聊天时(您可能正在使用new user
事件),请将用户的ID保存在connectedClients
。
connectedClients[username] = socket.id;
其中username
是用户连接到聊天系统时发送到服务器的名称。 (我希望你知道怎么做。如果没有,请问我。)
然后我们让一个监听器听取privateMessage
事件并向该特定用户发出消息,我们这样做:
socket.on('privateMessage', function(to, message) {
var id = connectedClients[to];
io.sockets.socket(id).emit('sendPrivateMessage', socket.username, message);
});
最后,在客户端,sendPrivateMessage
的听众会收到该消息,您可以相应地更新您的视图。
答案 1 :(得分:0)
这个想法是服务器通过用户名保存与其连接的每个套接字:users[socket.nickname] = socket;
所以每当用户向另一个用户发送消息时 - 你应该发出一个事件 - 向其发送另一个用户的用户名 - 拿走该用户的套接字并向他发送消息:
客户端:
socket.emit('sendPrivate','someusername','message');
socket.on('privateMsg',function(from,msg){
//write private message from user 'from'
});
服务器:
socket.on('sendPrivate',function(to,msg){
users[to].emit('privateMsg',socket.username,msg);
});