java.net.SocketException:接続のリセット


128

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

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


次の行があることに注意します。

socket.setSoTimeout(10000);

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

とにかく、それについて言及するだけで、うまくいけばレッドニシンではない。:-(


両側からスタックトレースがありますか?ネットワークアーキテクチャについてもう少し詳しく説明してください。(野生のインターネット上?同じマシン上?どこか中間?)それはいつも起こりますか?または断続的に?
Stu Thompson、

回答:


116

いくつかの原因が考えられます。

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

  2. より一般的には、接続への書き込みが原因で、もう一方の端がすでに正常に閉じています。つまり、アプリケーションプロトコルエラーです。

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

  4. Windowsでは、「ソフトウェアによる接続の中止」は「接続のリセット」とは異なり、エンドから送信するネットワークの問題が原因です。これに関するマイクロソフトのナレッジベースの記事があります。


@MattLyonsありがとう。それよりもはるかに優れたMSDNの記事があります。率直に言って、それを信じるのは難しいと思います。正しいソースIPアドレスとターゲットIPアドレスが確立されるまで、接続は存在しません。私が見たMSDNの記事は、接続がタイムアウトする持続的なネットワークエラーに言及しています。
ローン侯爵、

48

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

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

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


追加情報に応じて更新:

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


いくつかの点で正しくありません。ガベージコレクションとプロセスの終了はどちらも、リセットではなく適切なクローズを引き起こしますが、ピアに続いて書き込みを行うと、EOSではなくリセットが発生する可能性があります。SocketTimeoutExceptionsは、リーダーが読み取りタイムアウトを設定した場合にのみ発生します。
ローンの侯爵2012

また、RSTが受信されたとは限りません。また、こちら側で生成されたことを意味する場合もあります。
ローンの侯爵

17

私はこのような奇妙な問題があったときはいつでも、私は通常のようなツールで座っWireSharkの前後に渡される生データでルック。物事が切断されているところに驚くかもしれませんし、読んでみたときにだけ通知されます。


9

恥ずかしいことですが、この問題が発生したとき、すべてのデータを読み取る前に接続を閉じるのは間違いでした。小さな文字列が返された場合は機能しましたが、おそらくそれが閉じられる前に、応答全体がバッファリングされたためです。

より長い量のテキストが返される場合は、バッファが戻ってくるため、例外がスローされました。

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


9

完全なトレースを非常に注意深く検査する必要があります。

サーバーソケットアプリケーションを使用して、java.net.SocketException: Connection resetケースを修正しました。

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

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

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

興味深いのはfor my JAVA Socket、クライアントが自分に接続し、ServerSocket何もis.read()呼び出しを再帰的に送信せずに接続を閉じる場合です。これは、このソケットから読み取るために無限のwhileループにいるため、閉じた接続から読み取ろうとしているようです。読み取り操作に以下のようなものを使用すると、

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継続的に取得しているときに、このスナップショットを取得しました。

ここに画像の説明を入力してください


6

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


それだけではこの例外は発生しません。
ローン侯爵

System.exit(0)がプログラムを強制終了し、誰もsocket.close()を呼び出さない場合は、接続が不良な状態にあり、適切に閉じられなかったためです。soooより適切に、ソケットを閉じずにシャットダウンするクライアントプログラムがあると言った;)これは悪いことであり、修正する必要があります。
ディーン・ヒラー

1
@DeanHillerいいえ、そうではありません。オペレーティングシステムは、アプリケーションと同じ方法でソケットを閉じます。
ローンの侯爵

@EJP ....わからない... System.exitでそれを再現できることはわかっているが、かなり前にOS / configを覚えていない.... socket.close( )サーバーで接続のリセットが防止され、より適切に動作しました。
ディーンヒラー

2
@DeanHiller 書き込みプロセスが書き込みを完了する前に、読み取りプロセスが終了しました。
ローンの侯爵2014年

4

Javaで作成されたSOAシステムでこの問題が発生しました。私はクライアントとサーバーの両方を異なる物理マシンで実行していて、それらが長時間正常に機能していたため、これらの厄介な接続のリセットがクライアントログに表示され、サーバーログに異常はありませんでした。クライアントとサーバーの両方を再起動しても問題は解決しませんでした。最後に、サーバー側のヒープがかなりいっぱいであることを発見したので、JVMが利用できるメモリを増やしました。問題は解決しました!ログにはOutOfMemoryErrorがなかったことに注意してください。メモリが不足しているだけで、使い果たされていません。


2

サーバーのJavaバージョンを確認してください。私のWeblogic 10.3.6がTLSv1上にあるJDK 1.7.0_75上にあったため、私に起こりました。私が消費しようとした残りのエンドポイントは、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を有効にする方法


多くの感謝、あなたは私に私の問題を解決するための新しい方向性を示します。そしてついに私はそれが事実であることを発見しました!!!
karl li

1

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


0

私の経験では、次のような状況によく遭遇します。

  1. 企業で働いている場合は、ネットワークおよびセキュリティチームにお問い合わせください。外部サービスへのリクエストでは、関連するエンドポイントに許可与える必要がある場合があるためです。

  2. 別の問題は、SSL証明書が、アプリケーションが実行されているサーバーで期限切れになっている可能性があることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.