【问题标题】:socket.io private messagesocket.io 私信
【发布时间】:2012-07-06 13:06:53
【问题描述】:

我一直在网上搜索,但没有运气。我试图弄清楚如何将私人消息从一个用户发送给另一个用户。有很多 sn-ps,但我不确定客户端/服务器交互。如果我有要发送到的套接字的 ID,我如何将其发送到服务器,以及如何确保服务器仅将消息发送到那个接收器套接字?

是否有任何人都知道的教程或演练?

【问题讨论】:

  • 我已经创建了一个包含所有用户的数组,然后使用了 io.sockets.socket(userID).emit,但它仍然没有发送。更新后的服务器文件是here,客户端文件是here,如果你能看一下,不胜感激!

标签: node.js socket.io message


【解决方案1】:

无需教程。 Socket.IO FAQ 在这方面非常简单:

socket.emit('news', { hello: 'world' });

编辑:人们在稍后询问如何获取 socket 对象时链接到这个问题。没有必要。当新客户端连接时,在您保存用户信息的任何对象上保存对该套接字的引用。我的评论来自下面:

在脚本顶部的某处,设置一个对象来保存用户信息。

var connectedUsers = {};

在您的.on('connection') 函数中,将该套接字添加到您的新对象中。 connectedUsers[USER_NAME_HERE] = socket; 以后可以轻松找回。 connectedUsers[USER_NAME_HERE].emit('something', 'something');

【讨论】:

  • 那是用'news' id 发送给用户? “新闻”、“你好”、“世界”的功能是什么??那个sn-p没有任何意义。如何从客户端获取消息和目标用户?...“socket.emit('news', { hello:'world'});”不是很简单..
  • 否,这将为连接到socket 的客户端引发news 事件。处理该事件的函数的第一个参数将是对象{hello: 'world'}。您需要在连接时保留对该套接字对象的引用以供以后使用。
  • 我了解 socket.emit('news', { hello: 'world' });,但我仍然无法理解如何向特定用户发送特定消息。 = 新闻是事件,hello:world 是数据,但目标用户在哪里?现在,我正在尝试 io.sockets.socket(userID).emit('news', { hello: 'world' });,但似乎没有发送任何内容。
  • 我不知道该怎么向你解释这个......我已经说过至少3次了......当用户连接时你需要挂在套接字上。 Socket.IO 应该如何神奇地知道您打算将套接字与用户关联? 它没有!您必须编写该代码。套接字是与特定用户相关联的。您需要保留一个对象、数组或其他东西,以便您将用户与套接字相关联。
  • 在脚本顶部某处,设置一个对象来保存用户信息。 var connectedUsers = {}; 在您的 .on('connection') 函数中,将该套接字添加到您的新对象中。 connectedUsers[USER_NAME_HERE] = socket; 以后可以轻松找回。 connectedUsers[USER_NAME_HERE].emit('something', 'something');
【解决方案2】:

我能想到的最简单的方法是使用所有用户的 id 或 name 作为键并将其套接字作为值的一部分,然后当你想向他们发送消息时你拉该套接字并在其上发出...类似这样的内容:

users[toUser].emit('msg',"Hello, "+toUser+"!");

【讨论】:

    【解决方案3】:

    这里有一段代码 sn-p 应该会有所帮助:

    客户端(发送消息)

    socket.emit("private", { msg: chatMsg.val(), to: selected.text() });
    

    其中to指的是要发送私信的id,msg是内容。

    客户端(接收消息)

    socket.on("private", function(data) {   
       chatLog.append('<li class="private"><em><strong>'+ data.from +' -> '+ data.to +'</strong>: '+ data.msg +'</em></li>');
    });
    

    chatLog 是一个显示聊天消息的 div。

    服务器端

    client.on("private", function(data) {       
        io.sockets.sockets[data.to].emit("private", { from: client.id, to: data.to, msg: data.msg });
        client.emit("private", { from: client.id, to: data.to, msg: data.msg });
    });
    

    【讨论】:

    • 在你的服务器端代码中,什么是客户端?为什么不是socket.on? chat_server.js 代码为here,客户端代码为example_chat.tpl.php
    • 好的...我发现 client 只是您用于 io.sockets.on('connection') 的名称。
    • to: selected.text() 获取收件人的用户名?所以,他的 socket.id 需要存储在对象中,但我在你的 sn-p 中没有看到?还是我错过了什么?
    • 这一行令人困惑:io.sockets.sockets[data.to].emit("private", { from: client.id, to: data.to, msg: data.msg }) ;出现错误:TypeError:无法读取未定义的属性“发射”
    • 这只是在同一公共窗口上模拟私人消息,真正的私人聊天是当我们将对话提取到新标签时,例如,对于该任务,我在几个月内未能找到有效的解决方案.
    【解决方案4】:

    在 socket.io 1.0 中使用

    io.sockets.connected[<socketid>]
    

    您可以只存储套接字 ID。像这样:

    var users = {};
    users[USER_NAME] = socket.id;
    

    然后:

    io.sockets.connected[users[USER_NAME]]
       .emit('private', {
           msg:'private message for user with name '+ USER_NAME
       });
    

    【讨论】:

      【解决方案5】:

      如果您有一个使用 uid 注册用户的网站,那么您可以为每个用户创建一个房间并按用户的 uid 命名房间。

      首先将客户端连接到服务器:

      var socket = io('server_url');
      

      在服务器端创建一个用于检测客户端连接的事件:

      io.on('connection', function (socket) {}
      

      然后您可以使用socket.emit(); 向其中的客户端发出信号并询问当前用户的 uid。

      在客户端为此请求创建一个事件,然后将用户的 uid 发送到服务器。

      现在在服务器端将连接的套接字加入房间:

      socket.join(uid);
      console.log('user ' + socket.user + ' connected \n');
      

      现在您可以使用以下行向用户发送私人消息:

      io.to(uid).emit();
      

      如果您使用上面的代码,那么已经从您的网站打开了多少标签用户并不重要。每个标签都将连接到同一个房间。

      【讨论】:

        【解决方案6】:

        虽然我们在这里有很好的答案。但是,我无法很快掌握整个客户端服务器的唯一用户标识,所以我发布了这个简单的步骤,以帮助那些像我一样苦苦挣扎的人.....

        在客户端,获取用户的 ID,在我的情况下,我正在获取用户名...

        客户端用户注册

        //Connect socket.io     
        var systemUrl = 'http://localhost:4000';
        var socket = io.connect(systemUrl);
        
        //Collect User identity from the client side
        var username = prompt('Enter your Username');
        socket.emit('register',username);
        

        Listen to register 在服务器端将用户的套接字注册到连接的套接字

        服务端代码用户注册

        /*Craete an empty object to collect connected users*/
        var connectedUsers = {};
        
        io.on('connection',function(socket){
        
        /*Register connected user*/
            socket.on('register',function(username){
                socket.username = username;
                connectedUsers[username] = socket;
            });
        });
        

        从客户端发送消息

        $(document).on('click','.username',function(){
            var username = $(this).text(),
                message = prompt("type your message");
        
            socket.emit('private_chat',{
                to : username,
                message : message
            });
        });
        

        在服务器上接收消息并将其发送给私人用户

        /*Private chat*/
        socket.on('private_chat',function(data){
            const to = data.to,
                    message = data.message;
        
            if(connectedUsers.hasOwnProperty(to)){
                connectedUsers[to].emit('private_chat',{
                    //The sender's username
                    username : socket.username,
        
                    //Message sent to receiver
                    message : message
                });
            }
        
        }); 
        

        在客户端接收消息并显示

        /*Received private messages*/
        socket.on('private_chat',function(data){
            var username = data.username;
            var message = data.message;
        
            alert(username+': '+message);
        });
        

        这不是最好的,但是你可以从这里开始......

        【讨论】:

        • 我不明白这一行,请您解释一下。 if(connectedUsers.hasOwnProperty(to))
        • 它正在检查您的合作伙伴的节点是否仍在连接用户池中...
        • 不错的答案,简单高效。
        【解决方案7】:

        您可以为 USER_A 和 USER_B 之间的消息创建一个独特的房间,并且两个用户都必须加入这个房间。您可以使用 UUID 作为 ROOM_ID(以下示例中的“socketId”)。

        io.on('connection', socket => {
        
           socket.on('message', message => {
               socket.to(message.socketId).emit('message', message);
           });
        
           socket.on('join', socketId => {
               socket.join(socketId);
           });
        
        });
        

        Joining RoomsEmit Cheatsheet

        【讨论】:

          【解决方案8】:

          我让它工作的方法是引入一个“注册用户”事件。只要有注册用户,这基本上就会在客户端触发,然后甚至发出这个并传递“currentUser._id”

          Client Side: 
          
          var socket = io();
          <% if (currentUser) { %>
          socket.emit('registered user', "<%= currentUser._id %>");       
          <%  } %>
          

          服务器端:一旦“注册用户”触发,它会将当前用户套接字连接到名称为该用户 ID 的新房间。所以基本上每个注册用户都会在一个房间里,这是他/她的 uid。

          socket.on('registered user', function (uid) {
          socket.join(uid)
          });
          

          服务器端:有一个消息发送,我将消息发送到的用户的 id 传递到 msg 对象中,然后发送到那个特定的房间。

          // Private chat
          socket.on('chat message', function (msg) {
          const uidTo = msg.uidTo 
          socket.in(uidTo).emit('chat message', msg )
          }); `
          });
          

          【讨论】:

            猜你喜欢
            • 2013-01-10
            • 2014-03-17
            • 2016-11-12
            • 2017-04-13
            • 1970-01-01
            • 2013-02-06
            • 2016-05-21
            • 1970-01-01
            相关资源
            最近更新 更多