web-dev-qa-db-ja.com

java.net.SocketException:接続がリセットされました

ソケットから読み込もうとしているときに次のエラーが発生します。そのInputStreamに対してreadInt()を実行していますが、このエラーが発生しています。ドキュメントを熟読すると、これは接続のクライアント部分が接続を閉じたことを示唆しています。このシナリオでは、私はサーバーです。

クライアントのログファイルにアクセスできますが、接続は閉じられていません。実際、そのログファイルは接続を閉じていることを示しています。それで、なぜこれが起こっているのか、誰かが考えを持っていますか?他に何をチェックする必要がありますか?これは、おそらく限界に達するローカルリソースがあるときに起こりますか。


私は次の行があることに注意してください。

socket.setSoTimeout(10000);

readInt()の直前です。これには理由がありますが(長い話)、興味がありますが、これが指示されたエラーにつながる可能性がある状況はありますか?私は自分のIDEでサーバを動かしていて、たまたま私のIDEをブレークポイントのままにしておきましたが、IDEの自分のログにまったく同じエラーが表示され始めました。

とにかく、ちょうどそれを言及して、うまくいけば赤いニシンではないです。 :-(

101
Darryl

考えられる原因はいくつかあります。

  1. もう一方の端では、ここでは説明しませんが、意図的に接続をリセットしました。アプリケーションソフトウェアがこれを行うことはまれで、一般的には正しくありませんが、商用ソフトウェアでは未知ではありません。

  2. より一般的には、もう一方の端がすでに正常に閉じられたことを接続に書き込むことによって引き起こされます。つまり、アプリケーションプロトコルエラーです。

  3. ソケット受信バッファーに未読データがあるときにソケットを閉じることによっても発生する可能性があります。

  4. Windowsでは、「ソフトウェアが原因で接続が中断されました」は「接続のリセット」と同じではありませんが、端末から送信されたネットワークの問題が原因です。これに関するマイクロソフトサポート技術情報の記事があります。

100
user207421

接続リセットは単にTCP RSTが受信されたことを意味します。これは、相手が処理できないデータを相手が受け取ったときに発生します。その理由はさまざまです。

最も簡単なのは、ソケットを閉じてから出力ストリームにさらにデータを書き込む場合です。ソケットを閉じることによって、あなたは会話を終えたとあなたのピアに伝えました、そしてそれはあなたの接続について忘れることができます。とにかくそのストリームでさらにデータを送信すると、ピアはRSTでそれを拒否して、リスニングしていないことを知らせます。

他の場合では、介入するファイアウォール、あるいはリモートホスト自体があなたのTCP接続について「忘れる」かもしれません。これは、長時間データを送信しない場合(2時間が一般的なタイムアウトです)、またはピアが再起動されてアクティブ接続に関する情報が失われたために発生する可能性があります。これらの機能していない接続の1つにデータを送信すると、RSTも発生します。


追加情報に応じて更新します。

SocketTimeoutExceptionの取り扱いをよく見てください。ソケット操作でブロックされている間に設定されたタイムアウトを超えた場合、この例外が発生します。この例外がスローされてもソケット自体の状態は変更されませんが、例外ハンドラがソケットを閉じてから書き込みを試みると、接続リセット状態になります。 setSoTimeout()は、他のスレッドからソケットを閉じるなどの汚いことをすることなく、永久にブロックされる可能性のあるread()操作から抜け出すためのクリーンな方法を提供するためのものです。

41
erickson

私がこのような奇妙な問題を抱えているときはいつでも、私は通常 WireShark のようなツールで座り、やり取りされている生データを調べます。あなたは物事が切断されているところであなたは驚かれるかもしれません、そしてあなたはあなたが試して読んだときに通知されているだけです。

13
GEOCHET

それを言うのは恥ずかしいですが、私がこの問題を抱えていたとき、私がすべてのデータを読む前に私が接続を閉じていたのは単に間違いでした。小さな文字列が返される場合はうまくいきましたが、それを閉じる前に応答全体がバッファされていたためと考えられます。

大量のテキストが返される場合は、バッファが戻ってくるため、例外が送出されました。

あなたはこの見落としをチェックするかもしれません。 URLを開くことはファイルのようなものであることを忘れないでください。完全に読み取られたら、必ずそれを閉じる(接続を解放する)ようにしてください。

8
Scott S

フルトレースを非常に慎重に調べてください。

私はサーバーソケットアプリケーションを使っていて、Java.net.SocketException: Connection resetのケースを修正しました。

私の場合、何らかの理由で接続が閉じられているclientSocket Socketオブジェクトからの読み取り中に発生します。 (ネットワークの喪失、ファイアウォールまたはアプリケーションのクラッシュまたは意図的な閉鎖)

このSocketオブジェクトからの読み取り中にエラーが発生したときに、実際に接続を再確立していました。

Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

クライアントが私のServerSocketに接続し、何も送信せずにその接続を閉じると、面白いことにfor my Java Socketが発生します。is.read()は、自分自身を再帰的に呼び出します。以下のようなものを読み取り操作に使用すると、

while(true)
{
  Receive();
}

それから、stackTraceを以下のようにして取得します。

Java.net.SocketException: Socket is closed
    at Java.net.ServerSocket.accept(ServerSocket.Java:494)

私がしたのは、ServerSocketを閉じて接続を更新し、それ以上クライアントからの着信接続を待つことだけです。

String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

これにより、不明なクライアントソケットが失われた場合の接続が再確立されます。

private void tryReConnect()
        {
            try
            {
                ServerSocket.close();
                //empty my old lost connection and let it get by garbage col. immediately 
                clientSocket=null;
                System.gc();
                //Wait a new client Socket connection and address this to my local variable
                clientSocket= ServerSocket.accept(); // Waiting for another Connection
                System.out.println("Connection established...");
            }catch (Exception e) {
                String message="ReConnect not successful "+e.getMessage();
                logit();//etc...
            }
        }

下の画像からわかるように、try and catchがないと接続が失われたかどうかを理解できないため、他の方法を見つけることができませんでした。 Connection resetを継続的に取得している間にこのスナップショットを取得しました。

enter image description here

7
Davut Gürbüz

私は同じエラーがありました。私は今問題の解決策を見つけました。問題は、サーバーがストリームを読み取る前にクライアントプログラムが終了していたことです。

5
kml_ckr

私は、Javaで書かれたSOAシステムでこの問題を抱えていました。私はクライアントとサーバーの両方を異なる物理マシンで実行していましたが、それらは長い間問題なく動作していました。クライアントとサーバーの両方を再起動しても問題は解決しませんでした。最後に、サーバー側のヒープがかなりいっぱいになったことを発見したため、JVMで使用可能なメモリを増やしました。問題は解決しました。ログにOutOfMemoryErrorがないことに注意してください。メモリが不足しているのではなく、不足しているだけです。

4
Pino

私はSSH経由でサーバーにコマンドを送信しようとしているJavaプログラムにもこの問題がありました。問題は、マシンがJavaコードを実行していることにあります。リモートサーバーに接続する権限がありませんでした。 write()メソッドは問題なく動作していましたが、read()メソッドがJava.net.SocketException:Connection resetをスローしていました。クライアントのSSHキーをリモートサーバーの既知のキーに追加することで、この問題を解決しました。

1
pmartin8

サーバーのJavaバージョンを確認してください。 Weblogic 10.3.6がJDK 1.7.0_75にあり、TLSv1にあったので、私に起こりました。私が消費しようとした残りのエンドポイントは、TLSv1.2より下のものをシャットダウンしていました。

デフォルトでは、Weblogicは最も強力な共有プロトコルをネゴシエートしようとしました。詳細はこちらをご覧ください: HTTPS接続のhttps.protocolsシステムプロパティの設定に関する問題

サポートされているTLSを識別するために、冗長SSLログを追加しました。これは、TLSv1がハンドシェイクに使用されていたことを示しています。
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

この機能をJDK8互換製品にプッシュすることでこれを解決しました。JDK8のデフォルトはTLSv1.2です。 JDK7に制限されているものについては、TLSv1.2にアップグレードすることにより、Java 7の回避策のテストにも成功しました。私はこの答えを使用しました: Java 7でTLS 1.2を有効にする方法

0
behold