"Жесткое" разъединение Websocket не видно?

Я не уверен, что у меня есть тайм-аут по умолчанию (могу ли я установить это где-нибудь?), но, возможно, я чего-то не хватает. Когда клиентский браузер устанавливает соединение с websocket, я сохраняю постоянство. Затем, при отключении, я удаляю этот сохраняемый объект. Достаточно просто. Отключение обычно запускается, когда клиент закрывает браузер, но нет, когда клиент отключает свое wi-fi соединение (тестирование на MacBook Pro, но это не важно).

В контроллере Scala я регистрирую каждое сообщение in, но ничего не приходит, когда Wi-Fi отключается (из docs, я бы ожидал EOF?).

Я думаю, что это должно быть ошибкой, взятой из того, как я интерпретирую протокол WS сервер ДОЛЖЕН закрыть веб-узел  Соединение и СЛЕДУЕТ регистрировать проблему. Но последнее не происходит.

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)
}

Кто-нибудь испытал это? Я пробовал как простой контроллер, так и то, что соответствует моей конфигурации. Ни один из ws3 или ws2 контроллеров не выполняет трюк. Играть! код ниже:

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(""))
  }
}

Вид прост:

@(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

Ответ 1

Это не специфичная для Play Framework, а проблема, связанная с сетью. Случается, что если вы нормально отключитесь, другой конец отправит FIN-пакет, и сервер знает об этом. Если на другом конце нет сетевого подключения, он не может этого сделать.

Как определить, открыт ли сокет? При попытке чтения или записи вы получите исключение. Но с неблокирующей моделью, которая не происходит сама по себе. Поэтому в вашем случае я бы:

  • У вас есть тайм-аут
  • Сделать отправку сообщений по электронной почте в течение периода ожидания
  • Если пинг не поступает, отключите

или отправить пинги со стороны сервера (записать в сокет).