我有一个基于网络套接字的聊天应用程序(HTML5)。
浏览器通过wss打开一个到基于java的web套接字服务器的套接字连接。
当浏览器直接连接到服务器(没有任何代理)时,一切都很好。
但是,当浏览器位于企业代理之后时,浏览器套接字连接会在大约2分钟无活动后自动关闭。浏览器控制台显示"套接字已关闭"。
在我的测试环境中,我有一个SquidDansguard代理服务器。
IMP:如果浏览器在没有任何代理的情况下连接,则不会观察到这种行为。
为了让一些活动继续下去,我嵌入了一个简单的jquery脚本,它将每60秒向另一台服务器发出一个http GET请求。但这并没有帮助。在大约2分钟没有任何操作后,我仍然会在浏览器控制台中"关闭套接字"。
欢迎任何帮助或建议。
感谢
在我看来,这是一个功能,而不是一个bug。
在生产应用程序中,有一个问题与所谓的"半开放"套接字有关——请参阅这篇关于它的精彩博客文章
这种情况下,连接会突然丢失,导致TCP/IP连接在没有通知另一方连接的情况下断开。这种情况可能有很多不同的原因——wifi信号或蜂窝信号丢失、路由器崩溃、调制解调器断开、电池耗尽、停电。。。
检测套接字是否真的打开的唯一方法是尝试发送数据。。。但是,您的代理可能无法在不干扰应用程序逻辑的情况下安全地发送数据*。
两分钟后,您的代理服务器假设连接已丢失,并关闭其一端的套接字以节省资源并允许建立新的连接。
如果您的代理没有采取此预防措施,在足够长的时间内,您的所有可用资源都将被断开的连接占用,这些连接永远不会关闭,从而无法访问您的应用程序。
两分钟是很多。在Heroku上,他们将代理设置为50秒(更合理)。对于Http连接,这些超时通常要短得多。
对您来说,最好的选择是在2分钟内继续发送websocket数据。
Websocket协议通过实现内部ping机制来解决此问题-使用它。这些ping应该由服务器发送,浏览器直接用pong响应(不涉及javascript应用程序)。
Javascript API(至少在浏览器上)不允许发送ping帧(我想这是一个安全问题,可以防止人们使用浏览器进行DoS攻击)。
一些开发人员的一种常见做法(我认为这是错误的)是实现一个JSON ping消息,该消息要么被服务器忽略,要么导致JSON乒乓。
由于您在服务器上使用Java,因此您可以访问Ping机制,我建议您实现它
我还建议(如果您可以控制代理)将超时时间降低到更合理的50秒限制。
*生产过程中的情况实际上更糟。。。
因为有一长串中介(家庭路由器/调制解调器、NAT、ISP、网关、路由器、负载均衡器、代理…),所以您的应用程序很可能能够成功发送数据,因为它仍然"连接"到其中一个中介。
这应该会引发连锁反应,只有在一段时间后才会到达应用程序,并且只有当它试图发送数据时才会再次到达。
这就是为什么Ping帧期望返回Pong帧(意味着连接链是完整的。
p.S.
您可能还应该抱怨Java应用程序在某个超时后没有关闭连接。在生产过程中,这种疏忽可能会迫使您每隔一段时间重新启动服务器,或者遇到DoS情况(所有可用的文件句柄都将用于非活动的旧连接,您将没有空间容纳新连接)。
检查squid.conf中的request_timeout值。您可以通过request_timeout对此进行更改。这将不仅仅影响web套接字。例如,在我经常工作的环境中,需要使用perl脚本来生成各种配置。执行可能需要5-10分钟才能完成。我们的httpd和squid服务器上的超时值都必须提高以弥补这一点。
另外,还要查看connect_timeout值。默认为一分钟。。