【问题标题】:Chrome on Android : connection become dead after 30 minutesAndroid上的Chrome:30分钟后连接失效
【发布时间】:2017-09-23 12:28:52
【问题描述】:

我们正在使用我们自己的通知系统构建一个聊天室,不依赖于 GCM,而是使用 service worker + SSE。 在桌面上很好,但在移动 android 应用程序上(使用 cordova-crosswalk , chromium 53 )。 长时间运行的通知连接在 20-30 分钟后卡住,处于前台活动状态。 它不会因错误而死,只是不接收数据。完全没有错误,这很奇怪。无法重新连接,因为我们根本不知道连接是否已断开。

最干净的方法是什么?每 5 分钟重新启动连接是一种想法,但它并不干净。 代码

  runEvtSource(url, fn) {
if (this.get('session.content.isAuthenticated') === true) {
  var evtSource = new EventSource(url, {
    withCredentials: true
  });
}}

主动重新连接代码

var evtSource = this.runEvtSource(url, fn)
var evtSourceErrorHandler = (event) => {
  var txt;
  switch (event.target.readyState) {
    case EventSource.CONNECTING:
      txt = 'Reconnecting...';
      evtSource.onerror = evtSourceErrorHandler;
      break;
    case EventSource.CLOSED:
      txt = 'Reinitializing...';
      evtSource = this.runEvtSource(url, fn)
      evtSource.onerror = evtSourceErrorHandler;
      break;
  }
  console.log(txt);
evtSource.onerror = evtSourceErrorHandler

【问题讨论】:

  • 您是否尝试过定期(小于您似乎遇到的超时)发送数据以保持连接处于活动状态?
  • 不,我没试过,这意味着发送虚假数据?
  • 不是真正的“假”数据,而是仅用于保持连接活动的数据(通常称为 ping/pong)。
  • 当我检查时,连接仍然存在,但数据只是没有进出。

标签: javascript chat real-time long-polling server-sent-events


【解决方案1】:

我通常在 SSE 连接之上添加一个保持活动层。这种情况不会经常发生,但套接字可能会在没有正常死掉的情况下死掉,所以你的连接会安静下来,你不会收到错误。

所以,一种方法是,在您的获​​取数据函数中:

if(timer)clearTimeout(timer);
timer = setTimeout(reconnect, 30 * 1000);
...process the data

换句话说,如果距离上次获取数据超过 30 秒,请重新连接。根据您发送数据的频率选择一个值:如果 10% 的时间在数据事件之间有 60 秒的间隔,但从来没有 120 秒的间隔,那么将超时设置为高于 120 秒是有意义的.

您可能还希望通过将常规消息从服务器推送到客户端来保持活动状态。如果来自服务器的消息频率非常不规则,这是一个好主意。例如。我可能让服务器每 30 秒发送一次当前时间戳,并在客户端使用 45 秒的保持活动超时。

顺便说一句,如果这是一款移动应用程序,请记住用户是否会体会到减少接收聊天消息的延迟带来的好处,而不是减少电池寿命的缺点。

【讨论】:

  • 当我检查时,连接仍然存在,但数据只是没有来或去。这是因为移动 android 的铬中的sockets can die without dying properly 吗?我想对此进行深入分析。由于激进的重新连接尝试,已重新连接任何断开事件或错误事件。只剩下没有错误的无声连接。
  • @PhyoArkarLwin 是的,这就是问题所在。例如。您的客户端和服务器之间的一个路由器已决定断开连接(在移动设备的情况下,可能只是因为它已打开很长时间)、崩溃或重新启动。
  • 更新了主动重新连接代码。对于路由器决定断开该代码修复的连接 - 它会在出现网络问题时尝试重新连接,我已经与特定的 ISP 进行了测试,该 ISP 会在 2-3 分钟后断开长时间运行的连接,可能是 websocket 或任何连接。 `对于手机来说,也许只是因为它已经开放了很长时间`我猜这是真实的情况
  • @PhyoArkarLwin 是的,SSE 应该为您重新启动。但是因为不可靠(我从来没有测量过是90%可靠还是99.99%可靠,关键是不是100%),你还是需要实现自己的keep-alive逻辑。遗憾的是 SSE 标准没有添加超时参数,所以它会在安静时自动连接。
  • 今天我设法找出了发生了什么:在后台模式(在小米 Max 上)2-3 分钟后,与服务器的 TCP 连接停止同步和回答 ACK 响应,最终出现“Send-Q "和服务器端。直到它回到前台。然后我尝试重试连接,这让事情变得更糟。 - nslookup 失败,从 adb-logcat 看来,小米防火墙服务阻止了它。
猜你喜欢
  • 2021-12-26
  • 2018-12-20
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 2017-09-21
  • 2020-03-31
  • 1970-01-01
  • 2015-06-21
相关资源
最近更新 更多