web-dev-qa-db-ja.com

TCP KeepAliveを使用したソケット切断の検出

TCP/IPを介してサードパーティのデバイスをホストするサーバーを開発していますが、突然の接続切断が発生しています(デバイスはセルラー経由で接続しています)。デバイス自体にデータを書き込まずに切断を検出する方法を見つける必要があります。

TCPキープアライブ機能を使用することを検討しましたが、Javaは、キープアライブ操作のタイミングを調整できないようです。

これを行うための提案された方法はありますか?

私の簡略化されたソケットコードは次のとおりです。

public class Test2Socket {
    public static void main(String[] args) {
        try {
            ServerSocket skt = new ServerSocket(1111);

            Socket clientSocket = skt.accept();

            clientSocket.setKeepAlive(true);

            System.out.println("Connected..");

            BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            String inputLine;

            while((inputLine = input.readLine()) != null)
            {
                System.out.println(inputLine);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

フィードバックをいただければ幸いです。

9
PeteMitchell

TCPスタックの組み込みのキープアライブを使用することはできません。これは、キープアライブ間隔をアプリケーションで調整できず、OSによって設定され、デフォルトはかなり高い(時間)。これはJavaに固有のものではありません。

妥当な時間内にタイムアウトする必要がある場合は、使用するプロトコルに何らかのキープアライブを実装する必要があります。私が見た高レベルのプロトコルのほとんどは、「そこにいますか?」を送信する、ある種のNOP機能を備えています。メッセージと相手は何もせずに「はい、私はここにいます」という返信を送信します。

8
Laszlo Valko

TCP Keep-Alivesの詳細については、私の答えを参照してください ここ

ただし、基本的にTCPキープアライブは古い接続を検出するための最良の方法である可能性があります。主な問題は、接続がチェックされる2時間前にOSのデフォルトが設定され、さらに11分間のキープアライブが行われることです。接続前のアライブパケットは実際にドロップされます。

TCPがすでに組み込まれている場合は、独自のアプリケーション層キープアライブプロトコルを作成しないでください。必要なのは TCPを設定 タイムアウト)== 2〜3分などのより合理的なものに。

残念ながら、TCPタイムアウトはJVM内からではなく、OSレベルで管理されるため、TCPタイムアウトを内部から構成することは困難です(不可能ではありません))。ソケットごとにコードを作成します。

3
Cory Klein

setSoTimeout(),を適切な値に設定して、読み取りタイムアウトを設定します。たとえば、予想される応答時間を2倍にし、結果のSocketTimeoutException.をキャッチします。

注意:「Java TCP KeepAlive」」のようなものはありません。

0
user207421

ソケットでsetKeepalive()を呼び出すと、システムパラメーター(調整可能)が使用されます。 (openjdk7を使用したDebian 8で確認しました。)

まったく同じ機能が必要だったので、プリロードしてJavaで動作する libdontdie という小さなライブラリを作成しました。

0
Andreas Florath

this ライブラリの作者はこちら:-)

前に述べたように、TCPプロトコル(キープアライブ)に直接実装された構成が難しい機能に依存しない限り、実際に接続を介してデータを送信せずに故障を検出することはほとんどできません。

参照されるライブラリは、従来のJavaソケットをカプセル化し、簡単に構成可能な定期的な接続チェックとACKを追加します(これらはアプリケーションプログラマーには見えません)。故障が検出されるとすぐに、すべての内接オブザーバーは通知されます(リアルタイムに近い可能性のある構成によって異なります)。

利点は、libがかなり使いやすいことです(そして少なくとも私自身のプロジェクトでは非常に信頼性があります)。

欠点は、アプリケーション層が接続チェックに使用されることを意図していないことです。つまり、基本的に、そのlibは、おそらく意図されていない方法で物事を使用しています。

補足:クライアントは携帯電話であるとおっしゃいました。リンクされたライブラリwill Androidで動作しますが、接続の問題を自分で処理する代わりに、 プッシュ通知サービス を確認することもできます。それは例えば改善することができますバッテリー消費。

0
m5c