为啥重新连接成功时socket.io客户端会发送离线消息?

Posted

技术标签:

【中文标题】为啥重新连接成功时socket.io客户端会发送离线消息?【英文标题】:why did the socket.io clients resend offline messages when reconnect succcess?为什么重新连接成功时socket.io客户端会发送离线消息? 【发布时间】:2019-07-06 18:47:33 【问题描述】:

我正在使用 socket.io 做一个聊天室。当客户端离线时(只是关闭wifi),我仍然通过消息向服务器发送消息(名为离线消息A)不会发送成功。一段时间后,客户端将收到断开连接事件,忽略它,我仍然向服务器发送消息(名为离线消息 B)。完成以上操作后,我打开wifi,客户端会重新连接成功。好的,问题是客户端重新连接成功后,服务器会收到所有的离线消息(A,B)。我无法弄清楚它是如何从脱机到重新连接 socket.io 成功的。

我知道离线消息 B 存储在 sendBuffer 中,如the question 中所述。并且客户端重连成功时会重新发送sendBuffer中的消息,但是为什么离线消息A仍然可以成功发送到服务器呢?我已经编码来显示这个问题

/*
* Client side
*/
onClickSend = (value) => 
    console.log('send message:', value)
    this.socket.emit('chatMessage', value);

connect = () => 
    if (!this.socket) 
        console.log('connecting...')
        this.socket = io(url, 
            query: 
                clientId: this.clientId
            ,
            forceNew:true,
        )
    
    this.socket.on('connect',()=>
        console.log('connected');
    )

    this.socket.on('error',(err)=>
        console.log('error happen:',err);
    )
    this.socket.on('disconnect',(reason)=>
        console.log('disconnect event:', reason);
    )
    this.socket.on('reconnect',(e)=>
        console.log('reconnect success:' , e);
    )


/*
* Server side
*/
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http)
const PORT  = 40001;
io.on('connection', function(socket) 
    const clientId = socket.handshake.query.clientId;
    console.log('client come...', clientId)

    socket.on('connect', function(data) 
        console.log('user connects socket');
    );

    socket.on('disconnect', (reason)=>
        console.log('event disconnect: ', reason, clientId)
        socket.removeAllListeners()
        socket = null
    )
    socket.on('error', (err)=>
        console.log('error happen: ', err, clientId)
    )

    // the server will receive all the offline messages(message A, B)
    // send after the network is down when the client 
    // reconnect success.
    socket.on('chatMessage', (message)=>
        console.log('receive message: ', message, clientId)
        io.emit('chatMessage', message)
    )

);


http.listen(PORT, function() 
    console.log('listening on *:', PORT);
);

如我所见,服务器不会收到离线消息,但是当客户端重新连接成功时,服务器会收到所有离线消息。

【问题讨论】:

socket.io stop re-emitting event after x seconds/first failed attempt to get a response的可能重复 与那个问题有一些不同,我的比较简短,那个问题的答案并不能解决我的问题 【参考方案1】:

发射时socket.io code 的基数:

if (this.connected) 
    this.packet(packet);
 else 
    this.sendBuffer.push(packet);

所以offline messages A会被推送到sendBuffer,然后offline messages B会被推送到sendBuffer,然后当socket再次连接时,sendBuffer会被发送到服务器。

【讨论】:

以上是关于为啥重新连接成功时socket.io客户端会发送离线消息?的主要内容,如果未能解决你的问题,请参考以下文章

Socket io 在唱出并重新登录后返回两个数组

Socket.io 客户端在突然断开连接后无法重新连接到服务器

如何从客户端断开和重新连接 socket.io?

当套接字重新连接时,如何让 socket.io 服务器向特定套接字重新发送消息?

当谷歌浏览器中有很多 websocket 连接时,socket io 会中断

带有django和python socket io的事件