web-dev-qa-db-ja.com

接続を自動的に閉じるwebsocket

私は、Javaでアプリケーションを構築しています。このアプリケーションには、jettyベースのWebSocketサーバーが組み込まれています。クライアントは、Google Chromeのデフォルトのwebsocket実装です。接続が閉じられた後、サーバーとクライアント間で転送が行われない場合にのみ、すべてが正常に機能しています。誰が接続を閉じているのかわかりません:jettyサーバーまたはchromeブラウザー。

これに対する解決策は、x秒ごとにメッセージを送信することだと思いますが、より良い解決策を受け入れています。

だから...私の質問は:

  1. これはwebsocketプロトコルが必要とするもので、この場合chromeブラウザーは私の接続を閉じていますか?

  2. これは、桟橋に関連するもので、ウェブソケットプロトコルと多少関係があるものですか?この場合、桟橋でこれを無効にするにはどうすればよいですか?

  3. 別の問題はありますか??

ありがとう

更新:1メッセージ/秒を送信しても接続は閉じられます

66
Doua Beri

3番目の質問への回答:クライアントは、とにかく一時的なネットワークの問題に対処できるようにしたいと考えています。ユーザーがラップトップを閉じて会議を休止し、休止状態になるか、ネットワークが一時的に停止したとします。

解決策は、Webソケットクライアントでoncloseイベントをリッスンし、それらが発生したときに、クライアント側のタイムアウトを設定して、接続を再度開きます。

function setupWebSocket(){
    this.ws = new WebSocket('wss://Host:port/path');
    this.ws.onerror = ...;
    this.ws.onopen = ...;
    this.ws.onmessage = ...;
    this.ws.onclose = function(){
        setTimeout(setupWebSocket, 1000);
    };
}
38
Ant Kutschera

時々pingメッセージを送信する必要があります。デフォルトのタイムアウトは300秒だと思います。 ブラウザからwebsocket ping/pongフレームを送信

15

別の、かなり迅速で汚い解決策を見つけました。低レベルのアプローチを使用してWebSocketを実装し、onOpenメソッドを自分で実装すると、WebSocket.Connectionインターフェイスを実装するオブジェクトを受け取ります。このオブジェクトには、調整可能な setMaxIdleTime メソッドがあります。

9
LeoR

WebSocketServletFactoryインスタンスを使用して、Jettyサーバー側の設定で実際にタイムアウト間隔を設定できます。例えば:

        WebSocketHandler wsHandler = new WebSocketHandler()
        {
            @Override
            public void configure(WebSocketServletFactory factory)
            {
                factory.getPolicy().setIdleTimeout(1500);
                factory.register(MyWebSocketAdapter.class);
                ...
            }
        }
7
user3499459

自分でこれに対する解決策を見つけました。設定するのは、ミリ秒単位のWebSocketServletのmaxIdleTimeです。その方法は、サーブレットの構成方法によって異なります。 Guice ServletModuleを使用すると、10時間のタイムアウトで次のようなことができます。

serve("ws").with(MyWSServlet.class, 
new HashMap<String, Sring>(){{ put("maxIdleTime", TimeUnit.HOURS.toMillis(10) + ""); }});

0未満は無限のアイドル時間です。

4
AkaZn

これはJettyの問題だと思います。アクティビティがないためにブラウザがWebSocket接続を閉じるのを見たことも、WebSocket接続をタイムアウトする他のWebSocketサーバーに遭遇したこともありません。

Jettyは、主にHTTPベースのアプリケーションサーブレットの構築に重点を置いていました。そのコンテキストでは、HTTP接続をかなり積極的にクリーンアップする必要があり、HTTPは長寿命の接続用に設計されていないため、デフォルトのタイムアウトを短くするのが妥当です。

あなたが説明した正確な問題は見ていません(アクティビティでも閉じます)が、30秒の非アクティブ後にWebSocket接続が閉じられるのがわかります。 Jettyの古いバージョンまたは他の何らかの理由で現在のバージョンでは、WebSocketアクティビティによってタイマーがリセットされない可能性があります。 BlockingChannelConnectorオブジェクトでsetMaxIdleTimeメソッドを使用してタイムアウト値を整数MAX_VALUEに設定することで、これを回避します。

3
kanaka

WebSocketServletを使用してJettyのwebsocketタイムアウト(最も可能性の高い原因)を構成する方法の例を次に示します(scalaでは申し訳ありませんが、構文はほとんど同じです)。

import javax.servlet.annotation.WebServlet
import org.Eclipse.jetty.websocket.servlet.{WebSocketServletFactory, WebSocketServlet}

@WebServlet(name = "WebSocket Servlet")
class WebsocketServlet extends WebSocketServlet {
  override def configure(factory: WebSocketServletFactory): Unit = {
    factory.getPolicy.setIdleTimeout(1000 * 3600)
    factory.register(classOf[ClientWebsocket])
  }
}
2
user1338062

このタイムアウトは実際にはTCP/IPの一部であり、解決策はたまに空のメッセージを送信するだけだと思います。

2
David Grayson

私も同様の経験をしており、セッションを短くしているのはブラウザかもしれないと考えています。 maxIdleTimeoutも設定しましたが、セッションは関係なくドロップされます。私には、セッションをタイムアウトしてから電話を切るのはクライアント(ブラウザ)のようです。

それを回避する方法がわからない。

1
AndersW