web-dev-qa-db-ja.com

「ピアによる接続リセット:ソケット書き込みエラー」の解決方法

サーバーからファイルコンテンツを読み取ると、次のエラーメッセージが返されます。

Caused by: Java.net.SocketException: Connection reset by peer: socket write error
at Java.net.SocketOutputStream.socketWrite0(Native Method)
at Java.net.SocketOutputStream.socketWrite(Unknown Source)
at Java.net.SocketOutputStream.write(Unknown Source)
at org.Apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.Java:215)
at org.Apache.Tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.Java:462)
at org.Apache.Tomcat.util.buf.ByteChunk.append(ByteChunk.Java:366)
at org.Apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.Java:240)
at org.Apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.Java:119)
at org.Apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.Java:192)
at org.Apache.coyote.Response.doWrite(Response.Java:504)
at org.Apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.Java:383)
... 28 more

私のサーブレットプログラムは

 response.setContentType("application/octet-stream");
 response.setHeader("Content-Disposition","attachment;filename="+filename);
 FileInputStream in = new FileInputStream(new File(filepath));
 ServletOutputStream output=response.getOutputStream();
 byte[] outputByte=new byte[4096];
 while(in.read(outputByte,0,4096)!=-1){
     output.write(outputByte,0,4096);//error indicates in this line
 }
 in.close();
 output.flush();
 output.close();

この問題を解決するには?

20
Babu R

同じ例外がありましたが、私の場合、問題は再交渉のプロセスにありました。実際、サーバーが暗号スイートを変更しようとしたときに、クライアントが接続を閉じました。掘り下げた後、jdk 1.6 update 22では 再ネゴシエーションプロセスはデフォルトで無効になっています のように見えます。セキュリティ上の制約によりこれを実現できる場合は、Sun.security.ssl.allowUnsafeRenegotiationシステムプロパティをtrueに。プロセスに関する情報を次に示します。

セッション再ネゴシエーションは、進行中のSSL通信中にクライアントまたはサーバーが新しいSSLハンドシェイクをトリガーできるようにするSSLプロトコル内のメカニズムです。再ネゴシエーションは当初、進行中のSSLチャネルのセキュリティを強化するメカニズムとして設計され、そのチャネルを保護するために使用される暗号キーの更新をトリガーします。ただし、このセキュリティ対策は、最新の暗号化アルゴリズムでは必要ありません。さらに、クライアントがサーバー上の特定の保護されたリソースにアクセスしようとするときに、クライアント認証を実行するためにサーバーが再ネゴシエーションを使用してクライアント証明書を要求できます。

さらに、この問題について excellent post があり、(IMHO)理解可能な言語で書かれています。

11
Dmitry

ソケットはクライアント(ブラウザー)によって閉じられました。

コードのバグ:

byte[] outputByte=new byte[4096];
while(in.read(outputByte,0,4096)!=-1){
   output.write(outputByte,0,4096);
}

最後のパケットの読み取り、その後の書き込みの長さは4096未満になる可能性があるため、次のことをお勧めします。

byte[] outputByte=new byte[4096];
int len;
while(( len = in.read(outputByte, 0, 4096 )) > 0 ) {
   output.write( outputByte, 0, len );
}

それはあなたの質問ではありませんが、私の答えです... ;-)

3
Aubin

私は同じ問題に小さな違いがありました:

フラッシュ時に例外が発生しました

それは異なる stackoverflow issue です。簡単な説明は、間違った応答ヘッダー設定でした:

response.setHeader( "Content-Encoding"、 "gzip");

圧縮されていない応答データコンテンツにもかかわらず。

そのため、ブラウザーによって接続が閉じられました。

0
Kayvan Tehrani

「解決」する正しい方法は、接続を閉じてクライアントを忘れることです。クライアントは、あなたがまだ書き込みをしている間に接続を閉じたので、彼はあなたを知りたくないので、そうですよね?

0
user207421

問題が発生しているようです

while(in.read(outputByte,0,4096)!=-1){

オフセットを進めないために無限ループに入る可能性があります(呼び出しでは常に0です)。試して

while(in.read(outputByte)!=-1){

デフォルトでは、outputByte.lengthまでをbyte[]に読み取ろうとします。このように、オフセットを心配する必要はありません。 FileInputStremの読み取りメソッド を参照してください

0
prajeesh kumar