2009-06-09 22 views
22

PuTTYと私の接続が失われてしまいます(Windows上でマニュアルipconfig /releaseを実行すると)、直接応答して接続が失われたことを通知します。Javaが接続の切断を検出しました

自分のインターネット接続を監視して(信頼できるサーバーに)Javaプログラムを作成し、インターネットに障害が発生したときの日付/時刻を記録したいと考えています。

私はSocket.isConnected()メソッドを使用しようとしましたが、それは永遠に "true"を返します。 Javaでこれをどうやって行うことができますか?

答えて

18

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

だから、ある間隔で読んでみるだけです。読み込みに失敗した場合は、再接続を試みてください。

重要なイベントは、読み込みに失敗した場合、接続が失われたとき、新しいソケットが接続されたときです。接続が回復しました。

あなたは、アップタイムとダウンタイムを記録することができます。

+0

正しくない。読み取りタイムアウトを設定してトリガーすると例外が発生します。つまり、操作は失敗しますが、必ずしも接続が失われているとは限りません。 – EJP

+2

@EJPこれは必ずしも正しいとは言えませんが、何が起こっているかについての良い考えが得られます。 – jjnguy

+11

いいえ、それはできません。遅いサーバーと接続の切断を読み取りタイムアウトで区別することはできません。 – EJP

7

java.net.InetAddressクラスのisReachable()メソッドを使用しないのはなぜですか?この仕組み

は、JVMの特定の実装が、次のとおりです。

権限が得られるのであれば、それ以外の場合は、ポート7(エコー)上のTCP接続を確立しようとするICMPエコー要求を使用する一般的な実装宛先ホスト。

あなたはそれはあなたがisReachable()を持つのではなく、自分自身をECHO protocolを実行しているサーバーに接続することができました失敗したときに表示あなたのためにそれを行うと、データを読み書きし、それが失敗するのを待つことができるように継続的に開いている接続を維持したい場合。

+1

ええ、多分私は私の質問で明確ではなかった。私のシステムで時々起こることは、私のインターネットが数秒間落ち、すべての接続が閉じられるということです。 2番目のすべての後には問題ありません。 これを毎日監視して、これがどのくらいの頻度で発生したかをレポートしたいと思います。 – kresjer

+0

自分でECHOサーバーに接続し、データの送信と読み取りを続けることができます。これを答えに加えました。 –

+0

既存の接続がまだ開いているかどうかは 'isReachable()'とまったく関係ありません。 – EJP

0

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

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

+0

小さなサーバーに接続できなくなったときは、どのように分かりますか?そして、Javaの**主な**使用はAndroidのモバイルデバイスにあり、一定のpingやキープアライブはバッテリを殺すので、悪い考えです。 – user316117

0

yahoo/googleやこのような場所に接続する方が簡単かもしれません。

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

ニール

+0

既存の接続がまだ開いているかどうかは関係ありません。 – EJP

+0

質問は、これがうまくいく "私のインターネット接続を監視するJavaプログラム"を書く方法でした。 Javaはパテの接続が失われたかどうかを直接監視することはできませんが、一般的なネットワークの問題が発生したときは通知されます。 javaから "netstat"を呼び出して、別のプロセスからのネットワーク接続を監視することができます。 –

+0

WinSockを使用しているWindowsプログラマはイベントを登録できます。ケーブルを抜いても起動します。 (数秒遅れ)[https://stackoverflow.com/questions/44681648/in-android-how-can-i-receive-an-event-when-my-socket-closes-or-disconnects](link ) – user316117

1

あなたはソケットtimeout intervalを見しようとする場合があります。短いタイムアウト(私はデフォルトは '無限タイムアウト'と信じています)では、ホストが到達不能になったときに例外などをトラップすることができます。

+1

これはすべてのケースを検出するわけではありません。あなたは何かをソケットに読み書きする必要があります。 – tputkonen

10

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

接続が切断されたことに気付く唯一の方法は、一部のサーバーへのTCP接続を開き、そこからデータを読み取ることです。たぶん、最も簡単な方法は、FTPサーバーに接続して、小さなファイルやディレクトリリストを一度に取得することです。私は本当にこの場合に使用されることを意図した汎用サーバーを見たことがなく、FTPサーバーの所有者はこれを行うクライアントを好まない可能性があります。

(*)がありメカニズムと呼ばれるTCPキープアライブでもあるが、あなたはすべてのアプリケーションのためにそれを有効にする必要があり、多くのOSで、あなたが

1

オーケー迅速な接続の損失に気づくしたい場合に使用するのはとても実用的ではありません私はos.writeBytesを残している場合ので、私は最終的にそれが

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

私が望んだほどきれいではないが、それは働いていないで作業しました()。クライアントが正常に切断されている場合は

+17

これは間違いなく使用すべきではありません。これは、ほぼstackoverflow.comに対するDOS攻撃と見なすことができます! – tputkonen

+0

これを行うよりやさしい方法は、レンダリングされたページが小さかった場合(特に単純な "h"が行う場合)、このような一定の負荷に気付かないようなWebホストで単純なページ/スクリプトをホストすることです)。これは小さなフットプリントを提供しなければならず、1秒おきに呼び出しが行われると、サーバーはおそらくDOSに陥ることはありません。とにかく理論的に。 – Kingsolmn

+4

これはナンセンスです。 available()を呼び出すことは通常無意味です。それを呼び出して、結果を間違いなく投げ捨てます。睡眠は文字通り時間の無駄です。この技術は全く何も成し遂げません。 – EJP

4

read()は、他のXのためのreadLine()リターンヌル-1、readXXX()EOFExceptionをスロー返します。紛失したTCP接続を検出する唯一の信頼できる方法は、それに書き込むことです。最終的にはIOException 'connection reset'がスローされますが、バッファリングのために少なくとも2回の書き込みが必要です。

1

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

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

_ソケットが現在開いているかどうかを調べるには、isConnected()がtrueを返し、isClosed()がfalse_を返すことを確認する必要があります。これは当てはまりません。参照:[https://stackoverflow.com/questions/44685374/why-am-i-sending-an-rst-if-my-socket-is-connected-and-not-closed](リンク) – user316117

+0

@ user316117その質問は明確ではありませんが、isClosedがFALSEで、isConnectedがTRUEの場合、接続が管理され、接続が閉じられていないことを意味します。あなたが切断されていると思って、 "isClosed()"がFALSEを返したら、あなたはJDKのバグを発見しました。このドキュメントを参照してください。https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isConnected-- – Alboz

+0

@Alboz接続が管理され、* socket *はまだ閉じられていない。あなた自身の答えであなた自身を述べたように、接続とは何の関係もありません。独自のソケットをクローズしてから 'isClosed()== false'を取得しない限り、JDKのバグはありません。 – EJP

関連する問題