刷新时Socket.io断开连接?

Posted

技术标签:

【中文标题】刷新时Socket.io断开连接?【英文标题】:Socket.io disconnects when refreshed? 【发布时间】:2014-04-30 22:53:03 【问题描述】:

我正在尝试构建实时聊天,我正在使用 mongodb 和 socket.io 来存储消息和用户。

创建新用户时,该用户存储在 mongodb 和套接字对象中。

如果用户刷新页面,用户将从套接字对象中删除,这意味着现在为了让该人重新进入,他们必须创建一个新用户名并生成一个新套接字。

这是我的服务器端代码的样子

/*
|--------------------------------------------------------------------------
| Live socket communication with front end:
|--------------------------------------------------------------------------
|
|
*/

var users = ;

io.sockets.on('connection', function (socket) 

    // Listen to a new user then emit the user to all clients
    socket.on('new user', function (data) 

        // Check mongodb to see if the user exists and emit proper message
        models.Message.findOne(username:data,function(err,user)
            if(err)
                console.log('something went wrong')
            
            else if(user)
                socket.emit('username taken', 'something');
            
            else
                socket.emit('create user', data);
                socket.userName = data;
                socket.connected = true;
                users[socket.userName] = socket;
                io.sockets.emit('user name', Object.keys(users));
            
        );

    );

    socket.on('facebook id', function(data) 

        models.User.findOne(username:data.name, function(err, user) 
            if (user) 
                console.log('User already exists');
                socket.userName = data.name;
                socket.facebook_id = data.id;
                socket.connected = true;
                users[socket.userName] = socket;
                io.sockets.emit('user name', Object.keys(users));
             
            else 
                var newUser = new models.User(
                    username: data.name,
                    facebook_id: data.id
                );
                newUser.save(function(err, user) 
                    console.log('successfully inserted user/user: ' + user._id);
                );
            
        );

    );

    // Listen to a new message then emit the message to all clients
    socket.on('send message', function (data, callback) 

        io.sockets.emit('new message', message: data, username: socket.userName, facebook_id: socket.facebook_id);

    );

    // Logic when client disconnects
    socket.on('disconnect', function (data) 

        if(!socket.userName) return;
        seeder.disconnect(socket.userName);
        delete users[socket.userName]
        io.sockets.emit('user disconnected', Object.keys(users));

    );

);

您在我的断开连接中看到我从用户对象中删除了套接字。

我的问题是有没有办法在断开连接时保存套接字信息,然后如果同一个套接字尝试连接,它会识别用户并继续吗?

附加:我想也许我需要先专注于使用 mongodb 创建用户登录,然后使用该登录会话数据并将其传递给套接字,使用当前数据库创建套接字对象细节?这听起来是不是更有意义,这可能吗?

【问题讨论】:

【参考方案1】:

您可以使用 cookie 来识别用户。生成一个随机哈希,放入cookies中,这样在客户端和服务器建立连接时就会传输这些数据。

客户端代码可能如下所示:

function generateHash(len) 
  var symbols = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
  var hash = '';
  for (var i = 0; i < len; i++) 
    var symIndex = Math.floor(Math.random() * symbols.length);
    hash += symbols.charAt(symIndex);
  
  return hash;

if (!/\buser_id=/.test(document.cookie))  //if no 'user_id' in cookies
  document.cookie = 'user_id=' + generateHash(32);  //add cookie 'user_id'


//here goes establishing connection to server via `io.connect`

在服务器端你可以写:

io.sockets.on('connection', function (socket) 
  var cookie = socket.handshake.headers.cookie;
  var match = cookie.match(/\buser_id=([a-zA-Z0-9]32)/);  //parse cookie header
  var userId = match ? match[1] : null;
  //...

因此,您拥有userId 变量,该变量对于每个用户都是唯一的。然后你可以评论这一行:

delete users[socket.userName]

因为您应该保留用户数据。

您现在可以将users 对象与userId(不是用户名)作为键存储,并在每个连接上检查是否users[userId] != null。如果存在这样的用户,请使用他们的套接字信息

【讨论】:

我实际上找到了这个教程scotch.io/tutorials/javascript/… 我将尝试将套接字与我在这里学到的东西合并。以上绝对有助于掌握如何利用 cookie。

以上是关于刷新时Socket.io断开连接?的主要内容,如果未能解决你的问题,请参考以下文章

断开连接时销毁socket.io连接

断开连接/错误时清除 socket.io 缓冲区

socket.io 在空闲时断开客户端的连接

socket.io 服务器在注册客户端断开连接时非常延迟

Socket.io 不会在断开连接时向房间发送消息

更改请求标头 SOCKET.IO(无需断开连接和重新连接)