如何在客户端和服务器上同步 socketIO 连接 ID? [英] How synchronise socketIO connection ID's on client and server?

查看:66
本文介绍了如何在客户端和服务器上同步 socketIO 连接 ID?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 javascript GameClient,它使用 SocketIO 将消息发送到 nodeJs 服务器.多个用户可以单独打开GameClient,向服务器发送消息.

I have a javascript GameClient that uses SocketIO to send messages to a nodeJs server. Multiple users can open the GameClient separately and send messages to the server.

GameClient
GameClient  ---> NodeJS Server
GameClient

服务器可以使用 io.to(socketid).emit() 向特定客户端发送消息.代码如下所示:

The server can send messages to specific clients using io.to(socketid).emit(). The code looks something like this:

客户

this.socket = io({ timeout: 60000 })
this.socket.on('connect', () => Settings.getInstance().socketid = this.socket.id)
this.socket.on('reconnect', (attemptNumber:number) => console.log("reconnecting..."))

const json = JSON.Stringify({socketid:this.socket.id, name:"Old Billy Bob"})
this.socket.emit('user created', json)

SERVER(为了清楚起见而简化,这里只跟踪一个用户)

SERVER (simplified for clarity, just keeping track of one user here)

user = {}

io.on('connection', (socket) => {
    console.log('new connection')
    socket.on('disconnect', () => {
        console.log('user disconnected')
    });

    socket.on('user created', (json) => {
        user = JSON.parse(json)
    });
});

// demo code, send a message to our user
io.to(user.socketid).emit("message to one user")

问题

当客户端浏览器选项卡因任何原因完全处于非活动状态时,客户端会断开连接并重新连接并获取新的套接字连接 ID.这实际上在 Chrome 和 Safari 中经常发生.

When the client browser tab becomes inactive for any reason at all, the client disconnects and reconnects and gets a new socket connection ID. This actually happens a lot in Chrome and Safari.

服务器只知道旧的连接 ID,所以现在它不能再发送直接消息了.如何在客户端和服务器上保持套接字连接 ID 同步?

The server only knows the old connection id, so now it can't send direct messages any more. How do I keep the socket connection id synchronised on the client and server?

既然服务器也收到了重连事件,它怎么知道哪个用户重连了?

Since the server also gets a reconnected event, how does it know which user reconnected?

推荐答案

您的问题的答案很简单:您需要一种方法来识别谁是谁.这不是 socket.id 因为它只识别套接字,而不是用户,正如您已经注意到的那样.

The answer to your question is quite simple: you need a way to identify who is who. And that is not socket.id because this only identifies sockets, not users, as you've already noticed.

所以你需要一些认证机制.一旦用户通过身份验证,您就可以重用他的真实 id(无论它是数据库中的简单名称还是整数都无关紧要).然后在服务器端,您保留一组对 (true_id, socket_id).每当有消息到达该用户时,您就将其广播给所有匹配的 socket.io 对象.

So you need some authentication mechanism. Once a user authenticates you can reuse his true id (whether it is simply a name or an integer in a database is irrelevant). And then on the server side you keep a collection of pairs (true_id, socket_id). And whenever a message comes to that user, you broadcast it to all matched socket.io objects.

流程如下:

  1. 客户端与服务器进行身份验证,服务器向他发送自己的true_id,客户端将其存储在某处.客户端还可以存储一些 session_id 或其他一些机制,允许他在断开连接的情况下快速重新进行身份验证(注意:不要存储凭据,这是一个安全问题).
  2. 服务器以双向、多值映射的形式跟踪(true_id,socket_id)对(这是一个实现细节,这里应该使用什么样的数据结构,可能两个{} 对象就足够了).如果连接终止,则删除 (true_id, socket_id) 条目.请注意,对于给定的 true_id,可能还有其他一些 socket_id 活着.所以这并不意味着用户断开连接.这仅意味着此特定频道已死.
  3. 用户不关心socket_id,他们只关心true_id.你发出的是 {target_id: true_id, ...} 而不是 {target_id: socket_id, ...} 在客户端,当你想直接发送消息.
  4. 当服务器收到这样的带有 true_id 的消息时,它检索所有 (true_id, socket_id) 对并将消息传递给 all这些套接字(注意:也许你甚至不需要 socket_id,你可以简单地在这里存储 socket 对象).虽然这是一个业务逻辑:你允许每个用户有多个连接吗?我会.这里有很多边缘情况(例如客户端认为他断开连接,但服务器认为他仍然连接等)并且不幸的是不可能做到 100% 正确(由于网络的性质).但是只要稍加努力,就有可能让它在 99% 的时间里都能正常工作.
  5. 如果连接中断,则您的客户有责任自动重新连接并重新进行身份验证.在服务器端生成旧 true_id 的新 socket_id.
  1. Client authenticates with the server, the server sends him his own true_id, which the client stores somewhere. The client may also store some session_id or maybe some other mechanism that will allow him fast reauthentication in case of disconnection (note: do not store credentials, its a security issue).
  2. The server keeps track of (true_id, socket_id) pairs in the form of a double way, mutlivalue map (it's an implementation detail what kind of data structure should be used here, maybe two {} objects is enough). If a connection dies then (true_id, socket_id) entry is removed. Note that for a given true_id there still may be some other socket_id alive. And so it doesn't mean that the user disconnected. It only means that this particular channel is dead.
  3. Users don't care about socket_id, they only care about true_id. What you emit is {target_id: true_id, ...} instead of {target_id: socket_id, ...} on the client side, when you want to send a direct message.
  4. When the server receives such message with true_id inside, it retrieves all (true_id, socket_id) pairs and passes the message to all of these sockets (note: maybe you don't even need socket_id, you can simply store socket objects here). Although this is a business logic: do you allow multiple connections per user? I would. There are many edge cases here (like for example a client thinks that he disconnected, but the server thinks he is still connected, etc) and making this 100% correct is unfortunately impossible (due to the nature of networking). But with a bit of effort it is possible to make it work 99% of the time.
  5. If a connection dies then it is your client's responsibility to automatically reconnect and reauthenticate. New socket_id for old true_id is generated on the server side.

让我再次强调这一点:客户端根本不关心 socket_id.因为那不能识别它们.这仅标识一个频道.并且只有服务器关心这些信息.

Let me emphasize this again: clients don't care about socket_id at all. Because that doesn't identify them. This only identifies a channel. And only the server cares about this information.

这篇关于如何在客户端和服务器上同步 socketIO 连接 ID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆