【问题标题】:Getting list of clients using WebSockets使用 WebSockets 获取客户端列表
【发布时间】:2010-11-28 12:08:02
【问题描述】:

我正在构建一个多用户画板,但在获取和保持所有当前连接用户的更新列表时遇到了一些问题。我正在尝试找到将新客户端通知所有现有客户端并将现有客户端传递给新连接的客户端的最佳方法。我尝试这样做的原因是,当一个客户端画一条线时,所有其他客户端都会在列表中找到该客户端,并将线坐标添加到相应的数组中。

服务器.js

var sys = require("sys");
var ws = require('websocket-server');

var server = ws.createServer({debug: true});

server.addListener("connection", function(conn) {
// When a message is received, broadcast it too all the clients
// that are currently connected.
conn.send('NEW_SERVER_MESSAGE:Welcome!');
conn.send('USER_CONNECTED:' + conn.id);

conn.addListener("message", function( msg ){
    switch(msg) {
        case 'GET_ALL_ACTIVE_USERS':
            server.manager.forEach(function(con) {
                conn.broadcast('USER_CONNECTED:' + con.id);
            });
            break;
        case 'UPDATE_CURSOR':
            conn.broadcast( msg + '_' + conn.id );
            break;
        default:
            conn.broadcast( msg );
            break;
    }

});
conn.addListener('close', function( msg ) {
    conn.broadcast('USER_DISCONNECTED:' + conn.id);
});
});

server.addListener("error", function(){
console.log(Array.prototype.join.call(arguments, ", "));
});

server.addListener("listening", function(){
console.log("Listening for connections...");
});

server.addListener("disconnected", function(conn){
console.log("<"+conn.id+"> disconnected.");
});

server.listen(8002);</code>

我的JS网络代码:

sketchPadNet = function (b,s) {
var self = this;

this.host = "ws://localhost:8002/server.js";

this.id = null;
this.users = [];
this.heightOffset = 53;
this.scene = s;
this.connected = b;

var User = function(id) {
    this.id = id;
    this.nickname = id;
    this.lines = [];
    this.position = "";
};

this.init = function () {
    try {
        socket = new WebSocket(self.host);
        socket.onopen = function (msg) {
            socket.send('GET_ALL_ACTIVE_USERS');
        };

        socket.onmessage = function (msg) {
            var m = msg.data.split(':');
            switch(m[0]) {

            case 'USER_CONNECTED':
                console.log('USER_CONNECTED');
                var u = new User(m[1]);
                u.lines = [];
                u.nickname = u.id;
                self.users.push(u);
                console.log(self.users.length);
                console.log(self.users);
                break;

            case 'USER_DISCONNECTED':
                console.log('USER_DISCONNECTED');
                for(var i = 0; i < self.users.length; ++i) {
                    console.log(self.users[i]);
                    if(m[1] == self.users[i].id) {
                        self.users.splice(i, 1);
                    }
                }
                break;

            case 'DRAW_LINE':
                var tmpMsg = m[1].split('_');

                var id = tmpMsg[8];
                var userIndex = '';

                for(var i = 0; i < self.users.length; ++i) {
                    if(self.users[i].id == id) userIndex = i;
                }

                var p1 = (self.users[userIndex].lines.length < 1) ? new BLUR.Vertex3(tmpMsg[0], tmpMsg[1], tmpMsg[2]) : self.users[userIndex].lines[self.users[userIndex].lines.length - 1].point2;
                var p2 = new BLUR.Vertex3(tmpMsg[3], tmpMsg[4], tmpMsg[5]);

                var line = new BLUR.Line3D(p1, p2, tmpMsg[7]);
                line.material = tmpMsg[6];

                // add the newly created line to the scene.
                self.scene.addObject(line);
                self.users[userIndex].lines.push(line);
                break;

            case 'UPDATE_CURSOR':
                for(var i = 0; i < self.scene.objects.length; ++i) {
                    if(self.scene.objects[i].type == 'BLUR.Particle')
                        self.scene.removeObject(scene.objects[i]);
                }

                var coords = m[1].split('_');
                var id = coords[2];
                var userIndex = 0;

                for(var i = 0; i < self.users.length; ++i) {
                    if(self.users[i].id == id)
                        userIndex = i;
                }

                self.users[userIndex].position = new BLUR.Vertex3(coords[0], coords[1], 1);
                var p = new BLUR.Particle( self.users[userIndex].position, 4 );
                p.material = new BLUR.RGBColour(176,23,31,0.3);

                self.scene.addObject(p);
                break;

            case 'RECEIVE_ID':
                self.id = m[1];
                self.connected.nicknameObj.text = self.id;
                console.log(self.id);
                break;

                break;
            }
        };

        socket.onclose = function (msg) {
            // feck!
            self.connected.addServerError('Server disconnected, try refreshing.');
        };
    }
    catch (ex) {
        console.log('EXCEPTION: ' + ex);
    }
};

目前,当一个新的客户端连接时,它会发出一条消息并添加到一个数组中,当客户端断开连接时则相反。出于某种原因,虽然这不是保持更新?例如当客户端画一条线时,其他一些人会报告这个错误:

Uncaught TypeError: Cannot read property 'lines' of undefined

对不起,如果我在这里非常愚蠢,但感谢任何帮助!

干杯:)

【问题讨论】:

标签: javascript node.js websocket


【解决方案1】:

我试图通过查看代码来弄清楚它,但甚至没有出现错误的行号,无论如何这很难。

我想这是这里的问题:

conn.send('USER_CONNECTED:' + conn.id); // send the connect message to ONE user
conn.broadcast('USER_DISCONNECTED:' + conn.id); // send the disconnect to ALL users

因此,当用户连接时,您似乎只是错过了广播呼叫。

【讨论】:

    【解决方案2】:

    好的,真正的问题似乎出在客户端的'DRAW_LINE' 中。您确定将消息广播给所有用户,而不仅仅是将消息发送回客户端吗?

    错误指向您客户端代码中的这一行:

    var p1 = (self.users[userIndex].lines.length < 1) ? new BLUR.Vertex3(tmpMsg[0], tmpMsg[1], tmpMsg[2]) : self.users[userIndex].lines[self.users[userIndex].lines.length - 1].point2;
    

    请提供'DRAW_LINE' 的服务器代码。这个问题肯定是在那里出现的,而不是在其他任何地方。

    另外,self.users[userIndex]undefined。也许那个用户不存在?

    为什么你需要那个 for 循环?为什么不只是:

    if(self.users[id] != undefined) {
      var p1 = (self.users[id].lines.length < 1) ? new BLUR.Vertex3(tmpMsg[0], tmpMsg[1], tmpMsg[2]) : self.users[id].lines[self.users[id].lines.length - 1].point2;
    }
    

    【讨论】:

      【解决方案3】:

      我正在努力寻找最好的方法 通知所有现有客户一个新的 客户端,并通过现有的 客户端到新连接的客户端

      我建议您改为查看socket.io。如果浏览器不支持 websocket,它可以轻松完成此操作并故障回复到其他可用的传输。

      【讨论】:

        【解决方案4】:

        您可能需要考虑使用现有的服务器,该服务器内置了房间和用户列表等内容。为了进行比较,这里有一个使用 Union Server 的用 javascript 编写的多用户画板的教程:

        http://www.unionplatform.com/?page_id=2762

        这里是 Union Server 的文档化协议,其中包括房间和客户端加入/离开房间的消息传递系统的描述:

        http://unionplatform.com/specs/upc/

        可能会给你一些想法。

        科林

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-18
          • 1970-01-01
          • 1970-01-01
          • 2012-04-03
          • 2013-10-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多