Node.JS Socket.IO应用程序客户端识别问题。所有客户端显示的ID与上次连接的客户端相同

时间:2016-01-20 11:05:38

标签: javascript node.js socket.io

我正在尝试建立一个简单的系统,我将某些细节附加到客户端,如昵称,国家等,但我偶然发现了有关未正确注册信息的问题。

请查看我的代码:

index.js

var express = require('express'),
    app = express(),
    server = require('http').Server(app),
    io = require('socket.io')(server),

    glob = require('glob'),
    path = require('path'),
    fs = require('fs'),

    satelize = require('satelize');

var chat = require(__dirname + '/inc/chat');

server.listen(8888);

app.use('/public', express.static(path.join(__dirname, 'public')));

app.get('/', function (req, res) {
    res.sendFile(__dirname + '/views/index.html');
});

io.on('connection', function (socket) {
    chat.init(satelize,socket, function () {
        var client = chat.fetchClient(socket.id);
        socket.emit('client info', client);
        socket.on('message', function (msg) {
            console.log('Message recieved from ' + client.id);
            socket.emit('client info', client);
        });
        socket.on('disconnect', function () {
            chat.removeClient(client);
        });
    });
});

/inc/chat.js

module.exports = {

    /* client object initialization */
    client : {
        id          : null,
        username    : null,
        geo         : null
    },

    /* client array initialization */
    clients: [],

    init: function (satelize, socket, callback) {
        var init = this;
        if (typeof callback == "function") {
            var client = this.client;
            client.id = socket.id;
            satelize.satelize( { ip : this.ip(socket ) }, function(error, payload) {
                client.geo = payload;
                init.addClient(client);
                callback();
            });
        }
    },

    /* information retrieval*/
    ip: function (socket) {
        return cleanIp(socket.handshake.address)
    },

    /* client (the user) stuff */
    addClient: function (client) {
        if (client.id !== null) {
            this.clients.push(client);
            console.log(client.id + ' added to clients.');  
        } else {
            console.log('Cannot add client: id (null)');
        }
    },
    fetchClient: function (id) {
        for (var i = 0; i < this.clients.length; i++) {
            if(this.clients[i].id == id) {
                return this.clients[i];
            }
        }
    },
    removeClient: function (client) {
        console.log('removing client: ');
        console.log(client.id);
        var found = null;
        for (var i = 0; i < this.clients.length; i++) {
            if (this.clients[i] == client) {
                this.clients.splice(i,1);
                found = this.clients[i];
                break;
            }
        }
        if (this.clients.length > 0) {
            console.log('client list after removal: ');
            for (var i = 0; i < this.clients.length; i++) {
                console.log(this.clients[i].id);
            }
        } else {
            console.log('No clients in client array.');
        }
    }
}

function cleanIp (ip) {
    return ip.replace('::ffff:','');
}
在index.html中,我有以下js用于id和消息的可视化表示:

    var socket = io();
    socket.on('client info', function (data) {
        $('.client-id').text(data.id);
    });

    $('#input').keydown(function(e) {
        var key = e.which;
        if (key == 13) {
            if ($(this).val().length > 0) {
                socket.emit('message', $(this).val());
                $(this).val('');
            }
        }
    });

好的,如果我启动这个简单的节点服务器并在三个不同的浏览器选项卡中打开页面而不发送任何消息,则id似乎是正确的。

Three browser tabs in Google Chrome with the application running. Displaying unique udentifiers

但是,只要我从其中一个浏览器标签发送消息,它就会采用最后连接的客户端ID。

Three browser tabs in Google Chrome with the application running. Displaying the same udentifiers as the last connected client

当服务器启动时,它会在控制台中输出以下内容:

[nodemon] starting `node index.js`
/#h9sraEo5c8uLKgczAAAA added to clients.
/#opAfZCrRa64gFsR7AAAB added to clients.
/#x-WfhClfNsLEWE85AAAC added to clients.

如果我刷新第一个标签:

removing client:
/#x-WfhClfNsLEWE85AAAC
client list after removal:
/#x-WfhClfNsLEWE85AAAC
/#x-WfhClfNsLEWE85AAAC
/#pdlKD-v3K15_2voZAAAD added to clients.

如果我从该标签发送消息:

Message recieved from /#pdlKD-v3K15_2voZAAAD

如果我现在切换到另一个标签并写一条消息,服务器会输出与上面相同的消息,并在浏览器中更改id的可视化表示。

为什么连接的客户端的ID会更改为上次连接的客户端的ID?

2 个答案:

答案 0 :(得分:0)

问题是从line 4, chat.js开始的客户端对象正在被重用,而不会重置detalis,导致数据不唯一。

删除对象后,从line 16, chat.js开始动态生成对象,解决了所有已知问题,即所有id都是最后一个。

以下是更新的脚本:

index.js

var express = require('express'),
    app = express(),
    server = require('http').Server(app),
    io = require('socket.io')(server),

    glob = require('glob'),
    path = require('path'),
    fs = require('fs'),

    satelize = require('satelize');

var chat = require(__dirname + '/inc/chat');

server.listen(8888);

app.use('/public', express.static(path.join(__dirname, 'public')));

app.get('/', function (req, res) {
    res.sendFile(__dirname + '/views/index.html');
});

io.on('connection', function (socket) {
    socket.id = chat.uniqueId();
    chat.init(satelize,socket, function () {
        var client = chat.fetchClient(socket.id);
        socket.emit('client info', client);
        socket.on('message', function (msg) {
            console.log(client.id + ' sent: ' + msg);
            socket.emit('client info', client);
        });
        socket.on('disconnect', function () {
            chat.removeClient(client);
        });
    });
});

chat.js

module.exports = {

    /* client array initialization */
    clients: [],

    init: function (satelize, socket, callback) {
        var init = this;
        if (typeof callback == "function") {
            var client = {
                id : null,
                username: null,
                geo : null
            }
            client.id = socket.id;
            satelize.satelize( { ip : this.ip(socket ) }, function(error, payload) {
                client.geo = payload;
                var exists = null;
                if (init.clients.length > 0) {
                    for (var i = 0; i < init.clients.length; i++) {
                        if(init.clients[i].id == client.id) {
                            exists = client.id;
                        }
                    }
                }
                if (exists == null) {
                    init.addClient(client); 
                }
                callback();
            });
        }
    },

    /* information retrieval*/
    ip: function (socket) {
        return cleanIp(socket.handshake.address)
    },

    /* client (the user) stuff */
    addClient: function (client) {
        if (client.id !== null) {
            this.clients.push(client);
            console.log(client.id + ' added to clients.');  
        } else {
            console.log('Cannot add client: id (null)');
        }
    },
    fetchClient: function (id) {
        for (var i = 0; i < this.clients.length; i++) {
            if(this.clients[i].id == id) {
                return this.clients[i];
            }
        }
    },
    removeClient: function (client) {
        console.log('removing client: ' + client.id);
        var found = null;
        for (var i = 0; i < this.clients.length; i++) {
            if (this.clients[i] == client) {
                this.clients.splice(i,1);
                found = this.clients[i];
                break;
            }
        }
        if (this.clients.length > 0) {
            console.log('client list after removal: ');
            for (var i = 0; i < this.clients.length; i++) {
                console.log(this.clients[i].id);
            }
        } else {
            console.log('No clients in client array after last removal.');
        }
    },

    uniqueId : function() {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
            .toString(16)
            .substring(1);
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + s4();
    }

}

function cleanIp (ip) {
    return ip.replace('::ffff:','');
}

答案 1 :(得分:-1)

我在 index.js 中的socket.on('message')事件,您从回调中获得msg,但您使用的是具有当前客户端的client。 而是使用msg变量,如:

   socket.on('message', function (msg) { 
        //msg holds the client
        console.log('Message recieved from ' + msg.clientId);
        socket.emit('client info', client);
    });

从客户端发送clientId,如:

var id = socket.socket.sessionid;
socket.emit('message', {message: $(this).val(), clientId: id);

注意:此会话ID与服务器clientid不同。