Websocket'硬'断开不明显?

11 scala websocket playframework playframework-2.0

我不确定我是否遇到默认超时(我可以在某处设置吗?),但也许我错过了一些东西.当客户端的浏览器建立websocket连接时,我会保持持久性.然后,在断开连接时,我删除了该持久化对象.很简单.当客户端关闭浏览器时,通常会触发断开连接,但是当客户端关闭其Wi-Fi连接时(在MacBook Pro上进行测试,而不是这应该重要).

在Scala控制器中,我正在记录每条in消息,但是当wi-fi关闭时没有任何消息(从文档中,我会期望一个EOF?).

我认为这肯定是一个错误,从我解释WS协议 的方式来看,服务器必须关闭WebSocket连接,并且应该记录问题.但后者不会发生.

val in = Iteratee.foreach[String](x => {
  logger.info("Websocket msg: " + x)
   // expect EOF?
   x match {
     case "persist" => // persist some object
   }
}).mapDone { x =>
   // delete my persisted object (never happens unless browser/tab closed)
}
Run Code Online (Sandbox Code Playgroud)

有没有人经历过这个?我已经尝试过一个简单的控制器和符合我配置的东西.下面ws3ws2控制器都没有做到这一点.玩!代码如下:

object Application extends Controller {

  private def ws(out: PushEnumerator[String]) = {

    Logger.logger.info("ws()")

    val in = Iteratee.foreach[String](x => {
      Logger.logger.info("Websocket msg: " + x)
      try {
        x match {
          case "persist" => Logger.logger.info("PERSIST")
        }
      } catch {
        case e: Exception => {
          Logger.logger.info("NOT RECOGNIZED COMMAND, NO PERSIST")
        }
      }
    }).mapDone { x =>
      Logger.logger.info("STOP PERSIST")
    }
    in
  }

  def ws2() = WebSocket.using[String] { request =>

    Logger.logger.info("ws2()")

    val out = Enumerator.imperative[String]()
    val in = ws(out)

    (in, out)
  }

  def ws3() = WebSocket.using[String] { request =>

    Logger.logger.info("ws3()")

    val out = Enumerator.imperative[String]()
    val in = Iteratee.foreach[String](x => {
      Logger.logger.info("Websocket msg: " + x)
      try {
        x match {
          case "persist" => Logger.logger.info("PERSIST")
        }
      } catch {
        case e: Exception => {
          Logger.logger.info("NOT RECOGNIZED COMMAND, NO PERSIST")
        }
      }
    }).mapDone { x =>
      Logger.logger.info("STOP PERSIST")
    }
    (in, out)
  }

  def view() = Action { implicit request =>
    Ok(views.html.index.render(""))
  }
}
Run Code Online (Sandbox Code Playgroud)

视图很简单:

@(message: String) @main("Welcome to Play 2.0") {

@play20.welcome(message) }

<script type="text/javascript" charset="utf-8">
    var sock = new WebSocket("ws://192.168.1.120:9001/ws3");

    sock.onopen = function(event) {
        sock.send('persist');
    }
</script>
Run Code Online (Sandbox Code Playgroud)

路线:

GET     /ws2                          controllers.Application.ws2
GET     /ws3                          controllers.Application.ws3
GET     /view                         controllers.Application.view
Run Code Online (Sandbox Code Playgroud)

Mir*_*ari 2

这不是 Play 框架特定的问题,而是与网络相关的问题。发生的情况是,如果正常断开连接,另一端会发送 FIN 数据包,服务器知道它已挂断。如果另一端没有网络连接,则无法这样做。

那么如何判断套接字是否打开呢?尝试读取或写入时会出现异常。但对于非阻塞模型,这种情况本身不会发生。所以对于你的情况我会:

  • 有一个超时时间
  • 让 JavaScript 在超时时间内发送 ping
  • 如果没有 ping 到达,则断开连接

或从服务器端发送 ping(写入套接字)。