如何确保通过socket.io发送的消息已被客户端接收?

27
如何检查使用 socket.io 库发送的消息是否已被客户端接收。 在socket.io中有没有特殊的方法来完成这个操作?
谢谢你的回答!
3个回答

37

在定义事件处理程序时,您应该使用回调参数。

典型的实现如下:

客户端:

var socket = io.connect('http://localhost');
socket.emit('set', 'is_it_ok', function (response) {
    console.log(response);
});

服务器端

io.sockets.on('connection', function (socket) {
    socket.on('set', function (status, callback) {
        console.log(status);
        callback('ok');
    });
});

现在检查服务器端控制台,它应该显示'is_it_ok'。接下来检查客户端控制台,它应该显示'ok',这是确认信息。

更新

socket.io连接本质上是持久的。以下内置函数可让您根据连接状态采取行动。

socket.on('disconnect', function() {} ); // wait for reconnect
socket.on('reconnect', function() {} ); // connection restored  
socket.on('reconnecting', function(nextRetry) {} ); //trying to reconnect
socket.on('reconnect_failed', function() { console.log("Reconnect failed"); });

使用上述的回调函数选项实际上是以下两个步骤的组合:

socket.emit('callback', 'ok') // happens immediately

而在客户端上

socket.on('callback', function(data) {
    console.log(data);
});

所以你不需要使用定时器。回调函数会立即执行,除非连接处于以下状态之一- 'disconnect'、'reconnecting'、'reconnect_failed'。


我应该在客户端使用定时器来检查响应吗? - Bart
如果状态是“断开连接”,“重新连接中”,“重新连接失败”,会发生什么?是否有任何自动重试的机制?这是否需要计时器? - Dan Mandle

10
你可以使用socket.io的确认机制。
引用自socket.io文档:
有时,您可能希望在客户端确认消息接收时获得回调。
为此,只需将函数作为send或emit的最后一个参数传递即可。更重要的是,当您使用emit时,确认由您执行,这意味着您还可以传递数据。
在客户端上,只需使用您的数据发出事件,该函数将在服务器响应您的事件时被调用:
client.emit("someEvent", {property:value}, function (data) {
  if (data.error) 
    console.log('Something went wrong on the server');

  if (data.ok)
    console.log('Event was processed successfully');
});

在服务器端,您将收到数据和回调句柄以发送响应:

socket.on('someEvent', function (data, callback) {

  // do some work with the data

  if (err) {
    callback({error:'someErrorCode', msg:'Some message'});
    return;
  }

  callback({ok:true});
});

4
请注意,收到确认意味着远程主机已经接收到了消息,但是收到确认并不意味着远程主机没有接收到消息——在收到消息和发送确认之间,网络连接可能已经中断。 - Maël Nison
如果发生这种情况,那么套接字不就必须重新连接吗?我想你可以检查重新连接来解决这个问题。 - JVE999

1
当您将一个函数作为.send().emit()方法调用的最后一个参数添加时,当另一方接收到消息时,该函数将被调用。
socket.send('hi', function() {
    // if we are here, our salutation has been received by the other party.
});

我可能错了,但我认为该函数仅在与 send 一起使用时自动调用;当使用 emit 时,接收端必须手动调用它。 - Michelle Tilley
你是完全正确的。给emit的回调函数作为参数传递给另一侧的事件处理程序,因此事件处理程序可以使用自定义参数调用它。 - hasanyasin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接