EventSource在Android Firefox上不会自动重新连接

5
我正在尝试实现一个 HTML5 应用,它可以在桌面、安卓和 iOS 上工作。该应用的主要功能是无线向服务器发送关于哪些脚本运行以及接收来自该服务器的定期消息推送状态的命令。
服务器正在运行 nodejs,我决定使用 Server Sent Events 进行推送通知。这需要我在 Android 上使用 Firefox,因为原生的 Android 浏览器不支持 SSE。
我的实现都很好:节点服务器按照预期发布了事件,并且我的客户端 HTML5 / JavaScript 在桌面 Chrome/Firefox/Safari、我的 iPod iOS6 和 Android 2.2 手机上很好地接收到了它。
然而,有四种常见情况需要处理:
1. 设备失去 Wi-Fi 信号 2. nodejs 服务器崩溃(希望这并不常见!) 3. 将 iPod/Android 的浏览器放入后台时浏览其他应用程序等 4. iPod/Android 上的锁屏幕,同时浏览器正在运行
Chrome/Safari 在桌面和 iPod 上的表现非常完美,如下:
- 如果服务器崩溃,站点会自动重新连接,一旦服务器再次启动,即可获取推送的消息。 - 如果浏览器应用程序出于任何原因进入后台,仍然会在后台接收到这些消息,或者在回到前台时自动重新连接。
然而,Firefox 在桌面和 Android 上都过于急切地永久关闭了 EventSource 连接。只要浏览器失去与服务器的连接(无论是由于服务器崩溃、将 Firefox 应用程序置于后台还是锁定屏幕),EventSource 连接就会被关闭,而且永远不会尝试重新连接。当然,您可以在回到页面时重新加载页面,但这很烦人,特别是当您需要锁定屏幕时,因为您需要将手机放在口袋里(该应用程序需要在某些远足情况下使用)。
除了在 Android Firefox 中始终重新加载页面之外,是否有其他解决方案可推荐?下面是我的虚拟实现,每 5 秒发送一个随机数字。
服务器位于 /main/src.
src : function(req, res) {
req.socket.setTimeout(Infinity);    

// send headers for event-stream connection
res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
});
res.write('\n');

var messageCount = 0;
var process; 

function printEvent() {
    messageCount++; 
    rand = Math.floor((Math.random()*10000)+1);
    res.write('id: ' + messageCount + '\n');
    res.write("data: " + rand + '\n\n');        

    process = setTimeout(printEvent, 5000);
}
printEvent(); 

res.socket.on('close', function () {
    res.end();
    clearTimeout(process);
});
}

客户端

var source = new EventSource('/main/src');

source.onopen = function(e){        
    $("#test").html("Connected to server. Waiting for data..."); 
} 

source.onmessage = function(e){  
    $("#test").html("MSG: " + e.data);
}

source.onerror = function(e){  
    var txt;
    switch(e.target.readyState){  
    case EventSource.CONNECTING:  
        txt = 'Reconnecting...';  
        break;  
    case EventSource.CLOSED:  
        txt = 'Connection failed. Will not retry.';  
        break;  
    }
    $("#test").html("Error: " + txt);
}

Thanks!!


1
我只是想知道你的问题解决了吗?我还没有尝试过在Android Firefox中使用SSE,但是在桌面版Firefox 18中按ESC会终止SSE连接。从Firefox 20开始,它不会这样做了。 - Darren Cook
@DarrenCook,同样的bug也在我的火狐浏览器上出现了。对我来说,在谷歌浏览器上一切正常,但在火狐浏览器中聊天功能总是出故障。 - codefreaK
1个回答

4
我知道只有一个解决方案,它已经在许多库中使用:发送“心跳”消息。在客户端上,您可以检查是否在10秒钟(5000秒+一些延迟)内未从服务器接收到“随机数”,这意味着连接已经中断了,您应该重新连接。(使用原生EventSource您可以使用“close”方法,然后创建新的EventSource,或者您可以尝试使用https://github.com/Yaffle/EventSource)。

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