2

を実行しているサーバーに1つのスレッド(スレッドa)があります object = ois.readObject();。クライアントからLANワイヤを引き出すと、このスレッドは例外を取得せず、ストリームからの読み取りを続行します。

サーバー上の別のスレッド(スレッドb)は、接続がまだ有効であるかどうかを確認するために、1秒ごとにクライアントに1バイトを書き込もうとしています。checkingStream.writeObject(b);

このワイヤーを引っ張ると、IOExceptionからが得られcheckingStream.writeObject(b);ます。「スレッドb」で「スレッドa」にストリームからの読み取りを停止させ、コードを続行して例外をスローさせたいのですが。

threadA.interrupt();動作しません。何をすればよいでしょうか?

4

3 に答える 3

5

クライアントからLANワイヤを引き出すと、このスレッドは例外を取得せず、ストリームからの読み取りを続行します。

まあ、これは正しい振る舞いだと思います。インターネット(一般的に)およびIPベースのネットワークプロトコルは、ネットワークからの切断など、ローカルの中断に対して回復力があるように設計されています。

あなたの場合の問題は、読み取りスレッドが行っていることは、データが毎秒配信されることを期待していることをネットワークスタックに通知していないことです。したがって、ネットワークスタックは、ネットワークに問題があるのか​​、リモートサービスに問題があるのか​​、または1秒間データがないのかを判断できません。これは単に正常な動作です。

解決策は、EJPが推奨するように読み取りタイムアウトを設定するか、ネットワークが常に存在することを検出することを目的としたものを削除することです。後者をお勧めします。ネットワークが常に存在することを知る必要があるアプリケーション固有のオーバーライドがない限り、短期間のネットワークの中断を無視するか、アプリケーションレベルのプロトコルを回復力のあるものに設計するのが最善です。


threadA.interrupt(); 動作しません。何をすればよいでしょうか?

読み取りタイムアウトは1つのオプションです。ブロックされた呼び出しの妨害を解除する別の方法readは、で別のスレッド呼び出しclose()を行うことSocketです。これにより、ソケットに関連付けられたJavaストリームでの保留中の読み取りまたは書き込みが例外で終了します。


読み取りタイムアウトについて:

しかし、このフォーラムの他の回答は、それが安全ではないと言っています

タイムアウト例外を受け取った後、ソケットを使い続けようとすると安全ではありません。タイムアウトを使用する場合は、接続を破棄し、ソケットレベルのタイムアウト後に新しい接続を作成する必要があります。

これを実行したくない場合は、別の方法でタイムアウトを実装する必要があります。たとえば、読み取りスレッドの状態と読み取りスレッドが読み取るデータを監視する新しいスレッドを作成します。新しいスレッドが読み取りスレッドからのアクティビティを検出しない場合、アラームを発生させる可能性があります...接続が元に戻った場合に備えて、読み取り呼び出しで読み取りスレッドをブロックしたままにします。

于 2012-09-23T04:52:43.987 に答える
1

Socket.setSoTimeout()を使用して、読み取りタイムアウトを設定します。SocketTimeoutExceptionをキャッチします。

于 2012-09-23T04:36:19.820 に答える
0

Thread クラスを拡張してinterrupt()メソッドをオーバーライドする方が良いと思います。次のようになります。

@Override
public void interrupt()
{
    socket.close();
    super.interrupt();
}
于 2013-04-30T12:33:16.677 に答える