node.js / socket.io - 跟踪客户端

时间:2016-02-18 17:50:11

标签: javascript json node.js websocket socket.io

亲爱的朋友们在尝试跟踪聊天中登录的用户时,我遇到了一个小问题。聊天基于两个独立的通道,可以在命名空间的帮助下工作:

  1. chatInfra - 处理登录用户并发送欢迎信息。
  2. chatCom - 处理用户之间的留言。
  3. 我搜索了很多,但我发现只有理论上的解释才是最好的解决方案是将用户存储到数组中。因此,我试图通过将它们存储在数组中然后迭代它们来保持登录用户的跟踪,但结果仍然不好。

    问题是进入聊天后,屏幕上只显示第一个登录用户的名字,而第二个用户的名字不可见。

    这是我的服务器端代码,我正在尝试将用户存储到clients数组中:

        var clients = [];
    
        var chatInfra = io.of("/chat_infra").on("connection", function(socket){
            socket.on("set_name", function (data) {
              clients.push(data.name);
              socket.emit('name_set', data);
              socket.send(JSON.stringify({
                 type:'serverMessage',  
                 message:'Welcome!' 
             }));
            socket.broadcast.emit('user_entered', data);
            });
        });
    
        var chatCom = io.of("/chat_com").on("connection", function (socket) {
            socket.on('message', function (message) {
                message = JSON.parse(message);
                for(var key in clients){
    
                   if(message.type == "userMessage"){
                      message.username = clients[key];
                      console.log('message : ', message);
                      socket.broadcast.send(JSON.stringify(message));
                      message.type = "myMessage";
                      socket.send(JSON.stringify(message));
                   }
                }
    
            });
        });
    

    以下是它在浏览器中的显示效果:http://screencast.com/t/lshnfcGZ8E8

    以下是完整代码:https://gist.github.com/johannesMatevosyan/0b9f7e588338dbb6b7f5

1 个答案:

答案 0 :(得分:4)

我认为您通过使用不同的命名空间来创建不必要的过度杀伤。这是一个更清晰的工作示例,实现了相同的功能:

<强> server.js

var app    = require("express")();
var server = require("http").Server(app);
var io     = require("socket.io")(server);

var chat = io.of("/chat").on("connection", function(socket){

    socket.on("set_name", function (data) {

        socket.username = data.name;

        socket.emit("name_set", data);
        socket.emit("message", {
            type    :"serverMessage",
            message :"Welcome!" 
        });
        chat.emit("message", {
            type    :"serverMessage",
            message : data.name + " has joined the room.!"
        });
    });

    socket.on("message", function (message) {
        message.username = socket.username;
        chat.emit("message", message);
    });
});


app.get("/", function (req, res) {
    res.sendfile(__dirname + "/index.html");
});

server.listen(3000);

<强> client.js

var socket = io.connect('http://localhost:3000/chat');

socket.on('name_set', function (data) {
    $('#nameform').hide();
    $('#messages').append('<div class="systemMessage">Hello ' + data.name + '</div>');
});

socket.on('message', function (message) {
    var userNameHtml = message.username ? '<span class="name">' + message.username + ':</span>' : '';
    $('#messages').append('<div class="' + message.type + '">' + userNameHtml + message.message + '</div>');
});

$(function () {

    $('#setname').click(function () {
        socket.emit("set_name", { name: $('#nickname').val() });
    });

    $('#send').click(function () {
        socket.emit("message", {
            message : $('#message').val(),
            type    : 'userMessage'
        });
        $('#message').val('');
    });
});

我认为您不需要user_entered的单独事件处理程序,因为您将其视为常规消息而不对事件执行任何其他操作。还有几件事:

  • 您不需要先连接到服务器,然后再连接到命名空间地址,连接到后者就可以了。
  • 不要在回调中设置事件监听器,这会导致多次设置它们。