8

セレクターを使用してソケットを実行しています。ソケットがサーバーに接続されているかどうかを確認しようとしています。

Boolean connected = _channel.isConnected();

そしてそれは常にtrueを返します。コンピューターで空港(インターネット接続)をオフにしましたが、ソケットが接続されているかどうかを確認しても、trueが返されます。なぜですか?3秒ごとにサーバーにデータを書き込もうとしましたが、それでもソケットの状態が切断された状態に変わりません。

4

3 に答える 3

13

通常、OSレベルのネットワークをオフにすると、ソケットへの書き込みで例外がスローされるため、接続が切断されていることがわかります。

ただし、より一般的には、パケットが配信されているかどうかはわかりません。Java(おそらくCも)では、パケットがACKされているかどうかを確認する方法はありません。

TCP ACKを確認できたとしても、サーバーがパケットを受信または処理したことを保証するものではありません。これは、ターゲットマシンがパケットを受信し、それをメモリにバッファリングしたことを意味するだけです。その後、多くのことがうまくいかない可能性があります。

したがって、本当に確認したい場合は、トランスポートプロトコルに依存することはできません。アプリケーションレベルのACKが必要です。つまり、サーバーアプリケーションは、クライアントからメッセージを受信して​​処理した後、ACKメッセージを書き戻します。

クライアントの観点からは、サーバーにメッセージを書き込んでから、サーバーからACKを読み取ろうとします。それを取得した場合、そのメッセージが受信されて処理されていることを確認できます。ACKを取得できない場合は、何が起こったのかわかりません。経験的に、TCPが失敗した可能性があります。次の可能性は、サーバーがクラッシュしたことです。ACKがクライアントに到達できなかったことを除いて、すべてが正常に行われた可能性もあります。

于 2010-08-14T23:29:52.313 に答える
7

ソケットチャネルは、connectメソッドを呼び出すことで接続できます。接続されると、ソケットチャネルは閉じられるまで接続されたままになります。

物理接続の切断またはサーバー障害のためにサーバーが使用できなくなっても、チャネルは閉じられません。したがって、接続が確立されると、あなたがあなたの側のチャネルを閉じるまでisConnected()戻ってきます。true

サーバーがまだ使用可能かどうかを確認する場合は、ソケットの出力ストリームにバイトを送信します。例外が発生した場合、サーバーは使用できません(接続が失われます)。


編集

EJPの場合-コメントと回答をテストして再検討するためのコード:

public class ChannelTest {
     public static void main(String[] args) throws UnknownHostException, IOException {
      Socket google = new Socket(InetAddress.getByName("www.google.com"), 80);
      SocketChannel channel = SocketChannel.open(google.getRemoteSocketAddress());
      System.out.println(channel.isConnected());
      channel.close();
      System.out.println(channel.isConnected());
    }
}

私のマシンの出力は

true
false
于 2010-08-14T20:49:29.130 に答える
4

isConnected()は、チャネルオブジェクトを接続したかどうかを示します。これは、閉じた後にfalseを返すように指定されていませんが、明らかに接続されています。Andreasの回答を参照してください。基盤となる接続がまだ存在するかどうかを通知するために存在するわけではありません。あなたはそれを使用することによってのみそれを知ることができます:読み取りからの-1、または例外はあなたにそれを伝えます。

于 2010-08-15T01:24:19.513 に答える