如何找到 node.js websocket 消息的连接?

Posted

技术标签:

【中文标题】如何找到 node.js websocket 消息的连接?【英文标题】:How do I find a node.js websocket message's connection? 【发布时间】:2011-05-28 17:45:33 【问题描述】:

我正在为 node.js websocket 聊天服务器编写以下代码,并且想知道 conn 周围的变量生命周期问题是什么。

// chat-server.js
// Joshua Marshall Moore
// 12/20/2010

var ws = require("../../lib/ws/server");
var server = ws.createServer();

conns = [];
server.addListener("connection", function(conn)
    function runHandler(msg)
        server.broadcast(JSON.stringify("who": conns[conn], "when": Date.now(), "what": msg));
    

    function setupHandler(msg)
        if(conns.indexOf(msg)==-1 && msg!="Server")
            // name has not been taken yet
            conns[conn] = msg;
            conn.send("name ok");

            server.broadcast(JSON.stringify(
                "who": "Server", 
                "when": Date.now(),
                "what": msg + " has joined us"
            ));

            conn.removeListener("message": setupHandler);
            conn.addListener("message": runHandler);
            return;
        

        conn.send("name taken");
    

    conn.addListener("message", setupHandler);
);

server.addListener("close", function(conn)
    server.broadcast(JSON.stringify(
        "who": "Server",
        "when": Date.now(),
        "what": conns[conn] + " has left us."
    ));

    delete conns[conn];
);

server.listen(16007);

上面的代码将运行。服务器连接,提交名称,直到服务器说没问题。从客户端发送到服务器的任何消息都会中继到所有客户端。

我试图将连接用作稍后检索客户端先前提交的名称的密钥。 但是,当第二个客户端连接时,所有消息都会显示为来自最后一个连接的人。

我希望这里有人对 conn 变量在其整个生命周期中的作用域有所了解。 从外观上看,conn 是为服务器连接事件注册的匿名函数的本地函数。因此,在该匿名函数内部定义的函数本身可以访问 conn。

我更具体的问题是:每次建立新连接时都会调用匿名函数。这是否意味着每次发生这种情况时,函数 setupHandler 和 runHandler 都会使用与它们被调用的新连接相对应的 conn 副本,或者它们是否有机会相互混淆?

【问题讨论】:

【参考方案1】:

你不能在 javascript 中使用对象作为键,[conn] 所做的只是在conn 上调用toString()。而且几乎没有人会覆盖toString() 来返回有用的东西。

那么toString() 默认返回什么?对于对象,它返回[object Object]

conn 应该有一个 id 属性,它会给你一个唯一的值来用作键。

【讨论】:

啊哈!您是在建议我将三个字符分别添加到两个位置?【参考方案2】:

@Ivo 关于你不能使用对象作为键这一事实是正确的。

但是,正如您所指出的,问题肯定在于范围。 setupHandler 中的 conn 是最后连接的客户端。你为什么不做这样的事情:

server.addListener("connection", function(conn)
    conn.addListener("message", function(msg)
        if(conn.connected_username !== msg && msg!="Server")
            if(conn.isRegistered === true) 
              server.broadcast(JSON.stringify("who": conn.connected_username, "when": Date.now(), "what": msg));
             else 
              // name has not been taken yet so assign it!
              conn.connected_username = msg;
              conn.send("name ok");

              server.broadcast(JSON.stringify(
                "who": "Server", 
                "when": Date.now(),
                "what": msg + " has joined us"
              ));

              conn.isRegistered = true;
            
            return;
        

        conn.send("name taken");
    );
);

server.addListener("close", function(conn)
    server.broadcast(JSON.stringify(
        "who": "Server",
        "when": Date.now(),
        "what": conn.connected_username + " has left us."
    ));
);

server.listen(16007);

你为什么要把事情复杂化? :)

编辑:再次查看您的代码后,我意识到您正在使用侦听器来区分用户注册和消息。对代码进行了更改。

【讨论】:

以上是关于如何找到 node.js websocket 消息的连接?的主要内容,如果未能解决你的问题,请参考以下文章

node.js Websocket消息推送---GoEasy

node.js Websocket消息推送---GoEasy

对于实时 node.js 消息传递应用程序,如果没有 Heroku 中的 websockets,我会获得相同的功能吗?

无法从 React 客户端向 Node.js websocket 服务器发送消息

node.js基于websocket实时通信的实现—GoEasy

如何使用 node.js“ws”库服务器端监听后续消息