Frage

Ich bin mir nicht sicher, ob ich ein Standard-Timeout habe (kann ich das irgendwo einstellen?), aber vielleicht fehlt mir etwas.Wenn der Browser eines Clients eine Websocket-Verbindung herstellt, behalte ich die Persistenz bei.Dann lösche ich beim Trennen der Verbindung das persistente Objekt.Einfach genug.Die Trennung normalerweise wird ausgelöst, wenn ein Client den Browser schließt, aber nicht, wenn der Client seine WLAN-Verbindung ausschaltet (testen auf einem MacBook Pro, nicht dass das eine Rolle spielen sollte).

Im Scala-Controller protokolliere ich jeden in nachricht, aber nichts kommt durch, wenn das WLAN ausgeschaltet ist (von der Dok, Ich würde eine EOF erwarten?).

Ich denke, dass dies ein Fehler sein muss, wie ich das interpretiere WS-Protokoll der Server MUSS Schließen Sie den WebSocket Verbindung, und SOLLTE das Problem protokollieren. Aber letzteres passiert nicht.

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

Hat das jemand erlebt?Ich habe sowohl einen einfachen Controller als auch etwas ausprobiert, das meiner Konfiguration entspricht.Weder ws3 oder ws2 controller unten machen den Trick.Spiel!code unten:

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

Die Ansicht ist einfach:

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

Strecken:

GET     /ws2                          controllers.Application.ws2
GET     /ws3                          controllers.Application.ws3
GET     /view                         controllers.Application.view
War es hilfreich?

Lösung

Dies ist nicht spezifisch für das Play Framework, sondern ein netzwerkbezogenes Problem.Was passiert, ist, dass wenn Sie die Verbindung normal trennen, das andere Ende ein FIN-Paket sendet und der Server davon weiß, dass es auflegt.Wenn das andere Ende keine Netzwerkverbindung hat, kann es dies nicht tun.

Wie kann man feststellen, ob dann ein Socket geöffnet ist?Sie erhalten eine Ausnahme, wenn Sie versuchen zu lesen oder zu schreiben.Aber mit einem nicht blockierenden Modell passiert das nicht von alleine.Also in deinem Fall würde ich:

  • Haben Sie eine Auszeit
  • Lassen Sie JavaScript Pings innerhalb der Zeitüberschreitung senden
  • Wenn keine Pings ankommen, trennen Sie die Verbindung

oder senden Sie Pings von der Serverseite (schreiben Sie in den Socket).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top