Socket.io数据包在断开和重新连接之间丢失。

7
我正在使用socket.io连接智能手机(在Web框架中)到服务器并发送一些消息(每分钟几个短字符串,没有大的内容)。由于智能手机经常会有不稳定的连接,所以socket.io被迫不时重新连接。它会自动执行此操作,并将我想要发送的消息缓冲起来,一旦重新建立连接,这些消息就会作为一个包发送出去。因此,socket.io表现良好。
但是当我在socket.io注意到连接断开之前发送一条消息时,该消息会丢失。它不能被传输,但它也没有被socket.io缓冲。我对socket.io感到相当满意,但是这个问题困扰着我,因为我不发送很多消息,但确实需要那些我发送的可靠性。当连接建立时,所有消息都会完美地传输,因此我不需要检查。只有连接丢失和socket.io注意到它之间的第二个是我面临数据包丢失的关键时刻。
我一直在考虑模仿TCP行为,使用序列号和ACK,但感觉有点浪费。因此我的问题是:是否有人有轻量级的解决方案或遇到了此问题?我甚至不要求明确的代码-我可以自己写-但是消除这个特定问题的概念或类似的东西将是很棒的。
谢谢!
2个回答

3
为什么不将每个消息记录到数据库中?并使用socket.io的确认选项使其更好。

来自http://socket.io/#how-to-use服务器

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('ferret', function (name, fn) {
    fn('woot');
  });
});

客户端

<script>
  var socket = io.connect(); // TIP: .connect with no args does auto-discovery
  socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
    socket.emit('ferret', 'tobi', function (data) {
      console.log(data); // data will be 'woot'
    });
  });
</script>

谢谢。我真的没有想到这个很好的ack选项(我猜我会在我的当前修复中实现它),但它只能提供部分解决方案。这只处理成功的确认,并且我仍然需要确保如果消息没有到达,我自己重新发送它,而我在这里没有看到这样的功能。 - Jens Neumann
是的,但至少你知道它们没有收到,而且你已经将其存储好以备重发。 - Dslayer
实际上我并不需要,因为就目前来看,回调函数只有在消息确实被确认时才会被调用,而这恰恰与我想要的相反。我仍然需要自己找出消息未被接收的情况(使用自己的超时机制),将消息存储并重新发送。但无论如何,感谢您提供的这个功能肯定比我当前使用的方式更好 :) - Jens Neumann
我理解你的观点,但我更喜欢这种方式,而不是创建另一种机制,几乎肯定会做同样的事情,但只是不同的解决方案。如果你发现任何反向操作的东西(通知它没有收到消息),请告诉我。 - Dslayer
顺便说一下,你的客户端不知道另一个客户端是否已经收到消息,但服务器肯定知道。当消息发送给其他人时,服务器可以将其存储,如果另一个人超时或断开连接,它可以告诉发送者发送失败了。 - Dslayer

0
如果这很重要的话,我可能会模仿一个简单版本的TCP。只需在客户端存储缓冲区,并让服务器响应以确认消息,否则从缓冲区重新发送。

1
谢谢。我确实现在按照这种方式实现了它,另外还添加了一个功能,以确保服务器不会处理已经收到过的重复消息(这可能同样危险)。 - Jens Neumann

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