web-dev-qa-db-ja.com

Java失われた接続を検出する

私が使用しているときPuTTYと接続が失われる(または、Windowsで手動で_ipconfig /release_を実行すると)と直接応答し、接続が失われたことを通知します。

Java私のインターネット接続を監視するプログラム(信頼性の高いサーバーへの)を作成し、インターネットに障害が発生した日時をログに記録したい。

私はSocket.isConnected()メソッドを使用しようとしましたが、それは永久に「true」を返します。 Javaでこれを行うにはどうすればよいですか?

25
kresjer

さて、接続が中断されているかどうかを確認する最良の方法は、ソケットからの読み取り/書き込みを試みることです。操作が失敗した場合は、いつか接続が失われています。

したがって、必要なのは、一定の間隔で読み取りを試行することだけです。読み取りに失敗した場合は、再接続してみてください。

あなたにとって重要なイベントは、読み取りが失敗したとき-接続が失われたとき、および新しいソケットが接続されたとき-接続が回復したときです。

これにより、稼働時間と停止時間を追跡できます。

20
jjnguy

TCP/IPは「接続指向」のプロトコルですが、通常、アイドル接続ではデータは送信されません。 IPスタックによって1ビットが送信されることなく、ソケットを1年間開くことができます。接続が失われたことに気づくには、アプリケーションレベルでデータを送信する必要があります。(*)ADSLモデムから電話ケーブルを外して、これを試すことができます。アプリケーションに何らかのアプリケーションレベルのキープアライブメカニズムがない限り、PC内のすべての接続は維持されます。

したがって、接続が失われたことに気づく唯一の方法は、TCPあるサーバーへの接続を開いて、そこからデータを読み取ることです。おそらく、最も簡単な方法は、FTPサーバーに接続して小さなファイルを取得することです。 -またはディレクトリ一覧-たまにこのケースで実際に使用することを意図した汎用サーバーを見たことがなく、FTPサーバーの所有者はこれを行うクライアントを好まないかもしれません。

(*)TCPキープアライブと呼ばれるメカニズムもありますが、多くのOSでは、すべてのアプリケーションに対してアクティブ化する必要があり、接続の喪失にすぐに気づきたい場合に使用するのは実際的ではありません。

12
tputkonen

クライアントが正しく切断されている場合、read()は-1を返し、readLine()はnullを返し、他のXスローの場合はreadXXX()EOFExceptionを返します。失われたTCP=接続を検出する唯一の信頼できる方法は、それに書き込むことです。最終的にはIOException '接続のリセット'をスローしますが、次の理由により少なくとも2回の書き込みが必要です。バッファリング。

7
user207421

_Java.net.InetAddress_クラスの isReachable() メソッドを使用しないのはなぜですか?

これがどのように機能するかは、JVM実装固有ですが、次のとおりです。

一般的な実装では、特権を取得できる場合はICMP ECHO REQUESTを使用します。それ以外の場合は、宛先ホストのポート7(エコー)でTCP接続を確立しようとします。

接続を継続的に開いたままにして、失敗したときにそれを確認できるようにするには、isReachable()に実行させるのではなく、 ECHO protocol を実行しているサーバーに自分で接続して読み取り、データを書き込み、失敗するまで待ちます。

7
Dave Webb

わかりましたので、私はそれを最終的に動作させました

try
{
    Socket s = new Socket("stackoverflow.com",80);
    DataOutputStream os = new DataOutputStream(s.getOutputStream());
    DataInputStream is = new DataInputStream(s.getInputStream());
    while (true)
    {
        os.writeBytes("GET /index.html HTTP/1.0\n\n");
        is.available();
        Thread.sleep(1000);
    }
}
catch (IOException e)
{
    System.out.println("connection probably lost");
    e.printStackTrace();
}

思ったほどきれいではありませんが、os.writeBytes()を省略した場合は機能しません。

1
kresjer

ソケット timeout interval を確認してみてください。短いタイムアウト(Ibelieveデフォルトは「無限タイムアウト」)を使用すると、ホストが到達不能になったときに例外または何かをトラップできる場合があります。

1
poundifdef

Yahoo/googleまたはこのような場所に接続する方がおそらく簡単です。

    URL yahoo = new URL("http://www.yahoo.com/");
    URLConnection yc = yahoo.openConnection();
    int dataLen = yc.getContentLength() ;

ニール

0
Neil Wightman

数秒ごとにマシンにpingを実行できますが、これはかなり正確です。 DOSを実行しないように注意してください。

もう1つの方法は、リモートマシンで小さなサーバーを実行し、そのサーバーへの接続を維持することです。

0
Geo

Socket.Javaクラス内のisConnected() methodは少し誤解を招きます。ソケットが現在リモートホストに接続されているかどうか(閉じられていない場合など)は通知されません。 代わりに、ソケットがリモートホストに接続されたことがあるかどうかを示します。ソケットがリモートホストに接続できた場合、このメソッドは、そのソケットが閉じられた後でも、trueを返します。ソケットが現在開いているかどうかを確認するには、isConnected()trueを返し、isClosed()falseを返すことを確認する必要があります。例えば:

boolean connected = socket.isConnected() && !socket.isClosed();
0
Alboz