【问题标题】:Issues with long polling XMLHttpRequests and intermittent network connections长轮询 XMLHttpRequests 和间歇性网络连接的问题
【发布时间】:2012-12-21 18:32:38
【问题描述】:

我已经实现了一个长轮询连接,允许我在前端使用 Tomcat Web 服务器和标准 JavaScript 进行服务器端推送(彗星)。为了保持连接继续,我有一个简单的保持活动循环,一旦最后一个请求完成/失败,就会启动一个新请求。

在绝大多数情况下,这种连接工作得非常好,并且像我预期的那样保持活跃。但是,我注意到当用户的 Internet 连接断开时(例如,他们从 VPN 断开连接、拔下以太网等)并且我有一个待处理的 XMLHttpRequest 到服务器,我没有收到任何失败的迹象。正因为如此,连接无声无息地死掉了,除非我不断地向服务器发送请求以测试连接(这似乎违背了使用长轮询的目的),否则我无法知道它是否发生了。

这是我在 Chrome 中看到的请求对象,当它无声无息地死去时:

request: XMLHttpRequest
    onabort: function ()
    onerror: function ()
    onload: null
    onloadend: null
    onloadstart: null
    onprogress: null
    onreadystatechange: function ()
    readyState: 1
    response: ""
    responseText: ""
    responseType: ""
    responseXML: null
    status: [Exception: DOMException]
    statusText: [Exception: DOMException]
    upload: XMLHttpRequestUpload
    withCredentials: false

我设置了三个侦听器(onabort、onerror、onreadystatechange)以在它们被触发时提醒消息,但每当我与服务器的连接断开时,我什么也得不到。这是我形成请求的方式:

var request = new XMLHttpRequest();

//url is just the url to my servlet to handle this
request.open("GET", url, true);

//handlestatechange is just my standard handling code 
//that I've put an alert at the top of
request.onreadystatechange = handleStateChange;

request.onerror = function()
{
    alert("We encountered an error");
}

request.onabort = function()
{
    alert("I've had an abortion");
}

request.send(null);

这似乎是一个非常标准的情况,但我还没有看到任何关于如何允许长轮询连接从这种断开连接中恢复的对话。

我做错了吗?是否有其他更标准的方法来进行长轮询/彗星来规避这个问题?

对此的任何帮助将不胜感激, 谢谢

【问题讨论】:

    标签: javascript xmlhttprequest comet


    【解决方案1】:

    我相信处理这个问题的最好方法是将长轮询请求的持续时间限制在某个时间,T(例如 60 秒是一个不合理的值),然后在客户端使用超时来检测停滞状态。理想情况下,您应该使用 XHR timeout 属性,但 it isn't supported x-browser,尽管在 W3C 规范中。因此,您需要使用setTimeoutxhr.abort() 实现自己的支持。

    然后,客户端可以假设如果他们在 T 秒内没有得到响应,则连接已停止,并且可以中止当前请求并尝试重新连接。

    这工作得相当好,但确实意味着在检测客户端的连接何时停止时存在一些延迟(最多 T 秒)。对于长轮询请求,我不知道有很多事情要做。如果您确实需要更好的解决方案,那么您可能需要查看发送回心跳消息的streaming comet 连接或WebSockets

    这就是简单的答案。不幸的是,这对于各种奇怪的边缘情况来说都是一个不平凡的问题。例如,您可能关心也可能不关心具有连接超时的代理服务器,或者可能会在用户计算机上更改默认 TCP 超时的各种方式。这就是为什么我们看到像Socket.IO 这样的框架隐藏了很多这种丑陋之处。

    附:可能值得注意的是,您可以通过navigator.onLine在某些浏览器中监控在线状态,但它是poorly supported。它真正运行正常的唯一浏览器是 Chrome。它唯一真正告诉您的是用户是否因某种原因而处于离线状态。它不能告诉你他们有一个有效的连接。

    【讨论】:

    【解决方案2】:

    解决方法是开启 TCP keepalive。它是 TCP 中的一种机制,用于在失去可达性时关闭连接。您的应用程序不需要修改。您可以在操作系统或服务器应用程序中启用保活。

    【讨论】:

      猜你喜欢
      • 2022-06-16
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 2011-03-25
      相关资源
      最近更新 更多