不知道这是否是一个已知问题(我尝试搜索但一无所获)。 Safari浏览器的Mac似乎被悄悄丢弃由于不活动/ WebSocket连接空闲如果页面/选项卡不在焦点。
使Safari标签/页面不清晰; 记录websocket事件。
Websocket应该通过心跳功能保持活动状态。 在其他浏览器中看不到此行为,因此不太可能成为我的代码。
这是否可能是某种省电功能,可替代/忽略心跳?
使用DEBUG = *运行服务器将显示以下内容:
socket.io:client client close with reason ping timeout +0ms
socket.io:socket closing socket - reason ping timeout +0ms
我认为这意味着Safari关闭了连接,而不是套接字服务器或客户端实例。 但是,最奇怪的是,我注意到Safari有时会在30秒到1分钟后重新连接,但有时却没有,并且一直保持断开状态,直到页面聚焦为止。 尝试使用这种不一致的行为进行调试非常令人沮丧。
似乎有时它偶尔会重新连接(例如10分钟)。 同样,在相同的测试环境下完全不一致。
@twistedpixel ,重新连接延迟是指数级的(即:等待500毫秒,尝试重新连接,等待1000毫秒,尝试重新连接...)(源),这样可以解释这种行为。
当窗口再次获得焦点时,如何强制重新连接?
window.addEventListener("focus", () => socket.connect());
感谢您提供的信息,但主要的问题是我需要永久连接Web套接字,因为它用于在用户不在时向用户发送警报。 因此,重新聚焦的窗口焦点并不理想。
我认为这实际上是我的机器/安装特有的问题。 我注意到最初是在iMac上出现的问题,所以我决定只用新版本的Safari擦除MacBook,而我根本没有看到该问题。 我将标签最小化了一整天,它一次也没有断开。 因此,我尝试返回iMac并删除所有Internet插件并禁用所有扩展,但仍然看到了这种现象。
除了删除其首选项和某些其他文件外,Apple似乎没有提供完全重新安装Safari的任何方法。 或擦拭机器。 我的一部分只是想重新开始,但是我内部的开发人员会讨厌不知道是什么原因。
实际上,就您的指数重新连接点而言:正如您所说,第一次重新连接肯定会在断开连接后大约500毫秒内……为什么服务器会忽略它? 必须有一些阻止它触发重新连接的措施。
有点奇怪,因为如果我在断开事件中插入socket.connect()
,它再次连接就好了。 它必须每隔几分钟执行一次,但仍然必须这样做。 因此,我对为什么没有重新连接感到完全困惑! 我将进行更多的挖掘,看看是否能找出原因。
不幸的是,这是当今典型的浏览器行为,即使在台式机上也是如此。
我想我知道发生了什么事。 Safari确实是问题所在。
我认为所有的浏览器盖上的setTimeout和setInterval值在1000时的标签不在焦点。 Safari(愚蠢地)将其上限设置为1000 ,并进行了类似的操作,例如成倍增加延迟,导致每次迭代的时间都比最后一次长两倍。 这就是连接中断的原因。 socket.io的内部超时被延迟/删除,这说明了为什么在应有的情况下不进行重新连接。
因此,基本上,Apple决定像往常一样违反常规,从而导致糟糕的用户体验。 这些天他们真的很擅长。
我还没有发现为什么它会影响iMac而不是MacBook(我原本预期会相反),但是我将继续测试,看看是否能找到确切的原因。
@twistedpixel不仅是Safari。 参见http://blog.strml.net/2017/01/chrome-56-now-aggressively-throttles.html
在Primus中,我们通过反转心跳消息的方向(https://github.com/primus/primus/pull/534)解决了该问题。
@lpinca在整个过程中,我一直在想这个问题。 谢谢(你的)信息! 我一直在看Primus,但我不想这么快就重构整个代码库。 似乎值得付出努力。
@twistedpixel我的观点是,在Engine.IO中可能可以完成相同的操作,因此无需迁移到Primus。
FWIW,Safari Tech Preview似乎不受其他限制的影响。 也许苹果公司改变了他们的决定。 它仍在节流到1000毫秒,但似乎并没有增加任何东西。
我在iOS 12 Safari上遇到相同的问题。 如果我重新打开野生动物园,则websocket连接已消失。 有没有干净的解决方法来保持套接字存活?
当Safari进入后台(以防止电池耗尽)时,AFAIK iOS Safari会暂停某些进程,并且Websocket连接几乎肯定是这样的进程。 您不太可能在移动设备上找到解决方法。
好。 但是,如果我添加诸如onwindowfocus之类的事件侦听器,我仍然可以重新连接吗?
有没有人实施解决方法? 我们对寻找选择感兴趣,想知道其他人是否已经在尝试
您无需使用焦点事件,而需要使用Page Visibility API来检测移动应用程序窗口何时已被后台化。
我遇到了Azure SignalR的问题,并感谢@techpeace建议当前使用页面可见性API关闭页面隐藏上的连接并在页面可见时再次重新连接。但是遇到了快速切换选项卡的问题,该选项卡可以发送多个事件。 当前正在研究消除事件的可能性。.此外,在网络上发现的一般性建议也不鼓励基于用户代理检测的任何处理。因此,我的解决方案是使用页面可见性API,而与用户代理无关。
我使用所有这三种浏览器测试了几个小时,更改了pingTimeout
和pingInterval
值。 我发现是解决方案:
pingTimeout
> = 30000
mspingInterval
<= 10000
ms我相信最好的解决方案是更改pingTimeout = 30000
。 默认的pingInterval
是25000
ms毫秒,对于_at scale_项目而言,增加服务器将客户端ping客户端的频率每10s可能会太闲谈。
@darrachequesne我也可能在移动设备上遇到问题,如果我的手机屏幕处于待机状态,并且我再次在移动设备上打开浏览器,则io套接字会断开聊天。 请解决此问题。 这将是极大的缓解。
套接字io中此错误的任何更新?
在我的应用程序中,当用户尝试从其移动浏览器上载文件,并且在打开上载对话框时,如果套接字io需要15秒或更长时间来选择文件,则Socket io将其断开连接。
如果他们切换到另一个页面或选项卡,则在15秒钟后,套接字io再次将其断开连接,是否有办法解决此问题并保持套接字io处于活动状态/已连接,即使用户不在页面/文档上也没有关注?
@darrachequesne
我已使用Visibility API解决了此问题。
对我来说,Safari的主要问题-它没有时间关闭visible.hidden === true上的套接字,因此您需要在设备解锁后关闭websocket,然后重新启动它。
@ JustFly1984您是否有一些示例代码。 我已经可以看到可见性,但是我无法重新连接套接字。
所以现在这也发生在MacOS Safari中,仅供参考。
@calendee @anilanar我们不使用<ContextProvider />
,可见性位于顶部,websockets位于底部,websockets使用可见性中的上下文。
多谢您回覆JustFly1984。 实际上,最后,我不需要可见性API。 我只需要添加超时。 完成此操作后,我不再在iOS Safari上出现连接问题。
// Establish a Socket.io connection
// Initialize our Feathers client application through Socket.io
// with hooks and authentication.
client.configure(feathers.socketio(socket), {
timeout: 2000,
});
// Use localStorage to store our login token
client.configure(feathers.authentication(), {
timeout: 2000,
});
最有用的评论
我认为这是因为socket.io的当前版本依赖于客户端的setTimeout,这可能不如预期的可靠。
我们将其包含在v3中,因为这是一项重大更改。
相关: https :