获取使用WebSockets的客户端列表

时间:2010-11-28 12:08:03

标签: javascript node.js websocket

我正在构建一个多用户草图,并且在获取并保留所有当前连接用户的更新列表时遇到一些问题。我正在尝试找到通知新客户端的所有现有客户端的最佳方法,并将现有客户端传递给新连接的客户端。我试图这样做的原因是当一个客户端绘制一条线时,所有其他客户端在列表中找到该客户端,并将线路坐标添加到相应的阵列。

Server.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

对不起,如果我在这里非常愚蠢,但任何帮助表示赞赏!!

干杯:)

4 个答案:

答案 0 :(得分:2)

我试图通过查看代码来解决这个问题但是甚至没有出现错误的行号,反正这很难。

我想这是问题所在:

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

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

答案 1 :(得分:0)

好的,真正的问题似乎是在客户端'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;
}

答案 2 :(得分:0)

  

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

我建议你改为socket.io。如果浏览器不支持websockets,它可以轻松地执行此操作并故障回复到其他可用传输。

答案 3 :(得分:0)

您可能需要考虑使用内置房间和用户列表等内容的现有服务器进行比较,这是使用Union Server编写的javascript编写的多用户草图的教程:

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

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

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

可能会给你一些想法。

科林