【发布时间】:2020-11-09 13:22:17
【问题描述】:
我的服务器代码使用io.to(socketId).emit('xxx'); 向特定套接字发送消息,参考https://socket.io/docs/emit-cheatsheet/
但是当连接不好并且客户端断开连接并再次连接时,socketId会发生变化并且io.to(socketId).emit('xxx');然后失败。那么如何实现 re-emit 方法来处理重新连接?
我的问题与socket.io stop re-emitting event after x seconds/first failed attempt to get a response 的问题有点相反,从中我了解到socket.io client 可以在重新连接时重新发出。但服务器代码似乎缺乏这种支持。
---更新---
正如评论所说,我在这里显示“您保存过时的 socketId 值的代码上下文。”
首先,每个用户在我们的系统中都有一个唯一的 id,当 socket 连接时,客户端会发送一个登录消息,所以我保存了 userId 和 socketId 对。当我收到断开连接事件时,我会清除该信息。
第二,用户将通过redis pubsub(来自其他服务)获取消息,我将通过我记录的socketid将该消息发送给客户端。因此,当套接字连接时,我将订阅由 userid 标识的频道并在断开连接事件中取消订阅。
第三,当我收到 redis pub 事件而 socketId 值过时时,就会出现我的问题。实际上socketid的值是最新的,但是socket可能发送消息失败。
io.on('connection', async function (socket) {
socket.on('login', async function (user_id, fn) {
...
await redis
.multi()
.hset('websocket:socket_user', socket.id, user_id)
.hset(
`websocket:${user_id}`,
'socketid',
socket.id
)
.exec()
await sub.subscribe(user_id)
...
}
socket.on('disconnect', async function (reason) {
let user_id = await redis.hget('websocket:socket_user', socket.id)
await redis.del(`websocket:${user_id}`)
sub.unsubscribe(user_id)
...
}
//Here is what problem happens when socket is trying to reconnect
//while I got redis pub message
sub.on('message', async function (channel, message) {
let socketid = await redis.hget(`websocket:${channel}`, 'socketid')
if (!socketid) {
return
}
//so now I assume the socketid is valid,
//but it turns out clients still complain they didn't receive message
io.to(socketid).emit('msg', message) //When it fails how do I re-emit?
})
【问题讨论】:
-
您需要向我们展示您的代码上下文,您将在其中保存过时的
socketId值。 Socket.io 连接可以在用户导航或网络故障期间来来去去,因此,一般来说,您希望向已连接的用户发出信号,然后使用某种中间机制将用户映射到他们当前的 socketID,并保持该中间机制正常运行迄今为止,连接来来去去。 -
@jfriend00 感谢您回答我的问题。我更新了问题,你可以看看吗?