0

更新 このエラーは GZIP ストリームに関連していることがわかりました。それらを削除し、オブジェクト ストリームでラップされた GZIP ではなくオブジェクト ストリームを使用するだけで、問題は解決されます。例外はありません。誰かがそれを助けることができれば、それは素晴らしいことです。

また、GZIP を使用しているときに、エラーが非常にランダムになることにも気付きました。たとえば、ソケットを介して送信していたオブジェクト内のデータに大きく依存しているように見えました。オブジェクト データを変更すると、問題が解決する場合があります。たとえば、名前、姓、電話番号などの文字列値を含むユーザー オブジェクトがありました。それらがすべて設定されている場合、以下の問題が発生していましたが、それらをすべてクリアして空の文字列値にすると、以下の例外は発生しません。正直に言うととても奇妙です

GZIP ストリーム経由でオブジェクトを送信するクライアント/サーバー ソケットがあります。これは過去に問題なく機能しました。ただし、サーバーからクライアントに特定のデータを送信するときに、接続がリセットされます。

クライアントがサーバーに接続してリクエストを送信すると、サーバーはこれに応答してデータを送り返します。クライアント側で接続リセットの例外が表示されるため、エラーはサーバーからのものだと思います。

ここに例外のスニペットがあります

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:863)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:820)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)

すべてのクライアント/サーバー通信に同じソケット実装が使用され、テスト環境ではすべて正常に動作するため、これは非常に奇妙な問題です。また、例外が発生する前に同じコードが正常に使用され、起動時にクライアントがアプリケーションをロードするときにサーバーからデータが収集されます。

上記の情報から、渡される特定のデータに問題がある可能性があると思われますが、クライアントとサーバーの両方に接続のリセット以外の例外はありません。

デバッグ中に netstat ( netstat -anp ) を見ると、アクションが成功するとソケットが「CLOSE_WAIT」の状態になることがわかりますが、失敗した場合はソケットがすべて一緒に消えているように見えますが、どの状態にもありません。また、接続リセット例外が発生しない成功した場合でも、接続が終了すると多くの RST が発生することにも注意してください。私の TCP の知識はあまりよくありませんが、クリーンな接続は RST ではなく FIN で終わると思っていたでしょうか?

これがコードの例です

クライアント:

ObjectOutputStream out = null;
ObjectInputStream ois = null;

SSLSocketFactory sf = AdminClientApplet.getSSLContext().getSocketFactory();
Socket socket = null;

DataResponse dataRes = null;

try
{
    socket = sf.createSocket( server.getHost(), server.getPort() );

    // Need to connect to server and send request type,
    // ie what we are requesting to be sent to us
    GZIPOutputStream gZipOut = new GZIPOutputStream(socket.getOutputStream());
    out = new ObjectOutputStream(gZipOut);

    // write our request
    out.writeObject( dataReq );
    out.flush();
    gZipOut.finish();

    InputStream in = socket.getInputStream();
    GZIPInputStream gZipIn = new GZIPInputStream(in, 65536);
    ois = new ObjectInputStream(gZipIn);

    // read our response
    dataRes = ( DataResponse )ois.readObject();
    Log.CSSO.debug("Read object " + dataRes );
}
catch (IOException ie)
{
    Log.GUIP.error("IOException communicating with Admin Server on "+server, ie);
}
catch ( Exception e)
{
    Log.GUIP.error("Unexpected exception communicating with Admin Server on "+server, e);
}        
catch (Throwable t)
{
    Log.GUIP.error("Unexpected exception communicating with Admin Server on "+server, t);
}
finally
{
    // now close the connection gracefully
    CSSO.debug("closing socket");

    try
    {
        if ( out != null )
            out.close();

        if ( ois != null )
            ois.close();

        if ( socket != null )
            socket.close();
    }
    catch ( Exception e )
    {
        Log.CSSO.error( "Error closing socket connection during getDataFromServer()", e );
    }
}

サーバーはこの時点ですでに「リクエスト」を読み取っているため、これはリクエストされたデータをクライアントに返す部分にすぎません。サーバ:

Socket socket = null;

try
{
    socket = request.getSocket();
    socket.setTcpNoDelay(true);

    Log.CSSO.debug("Opening a response output stream to socket "+socket );

    gZipOut = new GZIPOutputStream(socket.getOutputStream(), 65536 );
    out = new ObjectOutputStream(gZipOut);

    // the actual 'data' we are going to return
    obj = getObject();

    Log.CSSO.debug("About to write " + obj + " to socket" + socket.getRemoteSocketAddress() );

    out.writeObject( obj );

    if (Log.CSSO.isDebugEnabled())
    {
        Log.CSSO.debug("Wrote DataResponse to socket " + obj );
    }

    out.flush();
    gZipOut.finish();
}
catch (IOException ie)
{
    Log.CSSO.error("IOException caught sending data to client", ie);
}
catch (Exception e)
{
    Log.CSSO.error("Unexpected exception caught sending data to client", e);
}
finally
{
    Log.CSSO.debug( "Closing socket to " + socket.getRemoteSocketAddress() );
    try
    {
        if ( out != null ) out.close();
        if ( socket != null ) socket.close();
    }    
    catch ( IOException e ) 
    {
    Log.CSSO.error("Unexpected exception caught closing socket", e );
    }
}

Log.FLOW.debug("< run");

デバッグ ログの場合、サーバーは例外なく最後まで実行されます (そのため、"< run" がログに書き込まれます)。ただし、クライアントエラー

ois = 新しい ObjectInputStream(gZipIn);

注目に値するもう1つの項目は、例外が発生するライブシステムがLinux(Centos)を実行していることです。Windowsで例外を複製できず、Linux Mintでも発生しません。これが原因だとは思いませんが、言及する必要があると思いました。

ここで問題の原因がわからないので、助けていただければ幸いです。

4

0 に答える 0