11

デフォルトのタイムアウトが発生しているかどうかはわかりませんが(これをどこかに設定できますか?)、何かが足りない可能性があります。クライアントのブラウザが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)
}

誰かがこれを経験しましたか?単純なコントローラーと、自分の構成に一致するものの両方を試しました。どちらも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
4

1 に答える 1

2

これはPlayFramework固有の問題ではなく、ネットワーク関連の問題です。正常に切断すると、もう一方の端がFINパケットを送信し、サーバーはそれがハングアップしていることを認識します。もう一方の端にネットワーク接続がない場合、ネットワーク接続はできません。

ソケットが開いているかどうかを判断するにはどうすればよいですか?読み取りまたは書き込みを試みると、例外が発生します。しかし、それ自体では起こらない非ブロッキングモデルを使用します。だからあなたの場合、私は:

  • タイムアウトする
  • JavaScriptがタイムアウト期間内にpingを送信するようにする
  • pingが届かない場合は、切断します

または、サーバー側からpingを送信します(ソケットに書き込みます)。

于 2012-10-02T20:56:27.213 に答える