scala - Websocket 'hard' 断开连接不明显?

标签 scala playframework websocket playframework-2.0

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

在 Scala Controller 中,我记录每个 in消息,但是 没什么当 Wi-Fi 关闭时通过(来自 docs ,我希望 EOF?)。

我认为这一定是一个错误,正如我如何解释 WS protocol 服务器必须关闭 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)
}

有没有人经历过这个?我已经尝试了一个简单的 Controller 和与我的配置相匹配的东西。都没有 ws3ws2下面的 Controller 可以解决问题。玩!代码如下:
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(""))
  }
}

View 很简单:
@(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>

路线:
GET     /ws2                          controllers.Application.ws2
GET     /ws3                          controllers.Application.ws3
GET     /view                         controllers.Application.view

最佳答案

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

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

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

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

    关于scala - Websocket 'hard' 断开连接不明显?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12681565/

    相关文章:

    java - 从 Java 调用具有多个隐式参数调用的主构造函数

    scala - 使用 SBT assemble 插件排除 jar

    带有 Play Framework 2 的 Scala 2.10Mx

    scaladoc 玩!带有 Scala 模块的框架

    java - 在 grizzly 上设置 websocket SSL

    scala - Sbt - 指定依赖扩展

    scala - 从 scala 中的嵌套 json 文件创建 spark 数据框

    java - Play 2.4 和 Deadbolt 安装

    c++ - MtGox API 和 websocketpp

    javascript - NodeJS 应用仅返回 Socket.io 欢迎消息