无法发送到特定客户端:套接字IO将其发送到每个客户端吗?

时间:2019-01-06 10:29:43

标签: javascript node.js express socket.io

是的,我已经仔细阅读了文档,该文档写得很好: Socket IO Cheatsheet

这是问题所在:当Express App中的会话被销毁时,我想通知用户注销。现在发生了什么:当我从会话中注销时,所有其他客户端(包括那些已经登录或尚未登录的客户端)都会收到一条消息,指出他们已注销。是的,我的快速应用程序运行良好-它们没有注销,但是我相信SOCKET IO会向他们发送消息。我运行了调试器,事实证明这两个客户端也是可区分的。

这是我的代码:

server.js:

var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
app.set('socketio', io);
io.on('connection', function (socket) {
  app.set('current_socket', socket);
  console.log('No of clients:', io.engine.clientsCount); 
});

userController.js:

exports.userLogout = function(req, res, next) {
    const sessionID = req.session.id;
    const io = req.app.get('socketio');
    const this_socket = req.app.get('current_socket');

    req.session.destroy(function (err){
        if(err) {
            console.error("userLogout failed with error:", err);
            return next(err);
        }
        else {
            console.log("this_socket:", this_socket);
            console.log("io:", io);
            this_socket.emit('userAction', { action: 'logout' });
            //other logic to remove old sessions from DB Session Store
            //and finally:
            res.status(200)
                .json({
                status: 'success',
                api_data: {'loggedIn':false},
                message: 'Logout successful.'
                });
        }
    }
}

我什至尝试这样做:

io.emit('userAction', { action: 'logout' });

但是事实证明它仍然会发送给所有客户端。我很确定某个地方不匹配,只是不知道在哪里。

2 个答案:

答案 0 :(得分:2)

如果要向特殊用户发送发射,则需要为每个会话ID创建空间

io.on('connection', function (socket) {
  app.set('current_socket', socket);
  var sessionId = socker.request.session.id
  //join room
  socket.join(sessionId);
});

userController.js:

exports.userLogout = function(req, res, next) {
    const sessionID = req.session.id;
    const io = req.app.get('socketio');
    const this_socket = req.app.get('current_socket');

    req.session.destroy(function (err){
        if(err) {
            console.error("userLogout failed with error:", err);
            return next(err);
        }
        else {
            console.log("this_socket:", this_socket);
            console.log("io:", io);
            this_socket.sockets.in(sessionID).emit('userAction', { action: 'logout' });
            //other logic to remove old sessions from DB Session Store
            //and finally:
            res.status(200)
                .json({
                status: 'success',
                api_data: {'loggedIn':false},
                message: 'Logout successful.'
                });
        }
    }
}

答案 1 :(得分:1)

您必须为每个用户定义唯一的套接字对象。我们有很多方法可以做到这一点。

以简单的方式,我们使用用户ID(唯一)作为存储套接字对象的键(映射方式:key(userId)-vaule(socketObj))。

跟随兔子:

用户登录后,客户端向服务器端发出一个事件(登录),该事件包括用户ID。

客户端:

[HttpPost("InserUsers")]
public async Task<List<ApiResponseMessage>> InserUsers()
{
    List<User> users = new List<User> {
        new User{ Name = "Jack" },
        new User{ Name = "Tom"},
        new User{ Name = "Tony"}
    };
    List<ApiResponseMessage> list = new List<ApiResponseMessage>();
    foreach (var user in users)
    {
        var response = Insert(user);
        list.Add(new ApiResponseMessage
        {

            Content = new { user },
            ReasonPhrase = response.ReasonPhrase,
            StatusCode = response.StatusCode
        });

    }
    return list;
}

public ApiResponseMessage Insert(User user)
{
    // do insert and if there is error
    if (user.Name == "Tom")
    {
        return new ApiResponseMessage()
        {
            StatusCode = HttpStatusCode.BadRequest,
            ReasonPhrase = $"Error"
        };
    }
    else
    {
        return new ApiResponseMessage()
        {
            StatusCode = HttpStatusCode.OK,
            ReasonPhrase = $"Successfully inserted"
        };
    }
}

服务器端:

// login success
socket.emit('userLoggedIn', {userId: THE_USER_ID})

userController.js:

io.on('connection', function (socket) {
  // app.set('current_socket', socket);
  console.log('No of clients:', io.engine.clientsCount);
  socket.on('userLoggedIn', function(data) => {
    app.set(data.userId, socket); // save socket object
  })
});
相关问题