检测 WebSocket 连接是否在服务器端终止

Detect if WebSocket connection is terminated on server side

我想以不同的方式处理不同的 WebSocket 连接终止情况。如果通过注销或浏览器关闭在客户端终止,我应该发送电子邮件。如果它在服务器端终止(例如在服务器重新启动后),我什么都不应该做。

有没有办法检测连接以何种方式终止?

我使用 Rails 4.2 和 em-websocket gem。

不应该(按设计)是确定 websocket 连接关闭原因的方法,但是...

...可以将一些 关闭事件编程到您的应用程序(客户端和服务器端)中,让您猜测其他原因。

此外,websocket 断开连接可能是由于连接丢失(网络电缆被拔出、丢失 Wi-Fi/cellular 接收、系统崩溃等),这种情况通常会在较长一段时间后检测到 - 连接似乎在关闭时打开(称为 half-open state )。

大多数服务器最多会在一分钟左右(很长)内检测到这种情况。阅读更多相关信息 here

对于服务器关闭,你可以利用 Karnel.trap method. If you were using Plezi 你可能可以在你的控制器中利用 on_shutdown(我有偏见,因为我是作者)。 . 从您的评论中我了解到 em-websockets 没有类似的回调,我对此感到抱歉。

要使用 trap 方法,您需要捕获退出信号并在转发之前执行任何必要的操作。即(它不是很干,你可以改进这个概念):

old_int_trap = trap('INT') do
   puts "do something"
   old_int_trap.respond_to?(:call) && old_int_trap.call
end
old_term_trap = trap('TERM') do
   puts "do something"
   old_term_trap.respond_to?(:call) && old_term_trap.call
end

或者,如果服务器出于自身原因(身份验证、不当行为等)关闭连接,您可以轻松设置一个标志,告诉 on_closeonclose?)回调到什么都不做。

客户端注销很容易 - 在注销用户之前发送一条消息。

浏览器关闭可以是默认设置(没有其他关闭原因)。

断开连接很难,但您可以保留一个变量来存储最后一条 websocket 消息的时间,如果自上一条消息以来超过 30 秒未收到任何消息,您可以假设出现问题。

...

但是:

就我个人而言,我会考虑在电子邮件等操作之前使用 completed websocket 消息'。我认为 "whitelisting" 事件是更好的方法。