0

UPDATE I've found that this error is related to the GZIP streams. If I remove them and just use Object streams rather than GZIP wrapped with Object streams then my issues are resolved, no exception. I have no idea why this is, if anyone can help that would be great.

I also noted while using the GZIP that the error would be very random. E.g it seemed to depend a lot on the data within the object that I was sending across the socket. Alter the object data and it would sometimes solve the issue. For example I had a user object which contained String values such as, first name, surname, phone number. If they were all set I was getting the below issue, however if I cleared them all to be empty String values then I wouldn't get the below exception. It's very bizarre to be honest

I have a client/server socket which sends object via GZIP streams. This has worked without issue in the past. However now I am seeing connection reset when sending certain data from the server back to the client.

The client connects to the server and sends a request, to which the server will reply and send back some data. I believe the error is from the server as the connection reset exception is presented on the client side.

Here is a snippet of the exception

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)

It's a very strange issue because the same socket implementation is used for all client / server communication and in our test environment everything works fine. Also the same code is used successfully before the exception occurs to collect some data from the server when the client loads the application on startup.

The above information leads me to believe there could be an issue with the specific data that is being passed, although the client & server both present no exception other than the connection reset.

Looking at netstat ( netstat -anp ) while debugging I can see successful actions result in a socket in the state of "CLOSE_WAIT", however unsuccessful ones the socket just seems to disappear all together, it's not there in any state. I also note that there is a lot of RST when the connections are finished, even for sucessful cases where I don't get connection reset exception. My TCP knowledge isn't great, but I would have thought a clean connection would end with FIN rather than getting RST?

Here is an example of the code

Client:

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 );
    }
}

The server has already read the 'request' at this point, so this is just the part that returns the requested data to the client. Server:

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");

When on debug logging the server runs all the way through to completion, without any exceptions ( so "< run" is written in the logs ). However the client errors at

ois = new ObjectInputStream(gZipIn);

The other item worth noting is that the live system, where the exception occours is running linux ( Centos ), where as I'm not able to replicate the exception on windows and it doesn't happen on Linux Mint either. I don't expect this would be the cause but just thought I should mention it.

Any help much appreciated as I'm lost as to the cause of the issue here.

james4563
  • 169
  • 1
  • 13
  • I should add that by "Can't reproduce" i mean I cannot reproduce it on any of our systems other than our live system. It's easy to replicate on the live system and happens consistently when requesting data. – james4563 Jun 17 '16 at 10:33
  • You need to have a good look at the *server* logs. This error is normally caused by the peer closing the connection while there is still pending data or data in flight, which in turn often means you sent it something it didn't understand. – user207421 Jun 17 '16 at 11:40
  • @EJP Is it correct for me to call close() on the socket server side as soon as I'm done? Or are you saying that you shouldn't call close() until I am sure the client has read the object returned? I wasn't sure if I should be not calling close() on the server and just letting the client call close() after it's finished reading the data? – james4563 Jun 17 '16 at 11:58
  • It's OK to close when you are done, but if the client has sent more data, or will send more, it will then get a connection reset. This is an application protocol error. You need to ensure that the server and the client both have the same notion of 'done '. – user207421 Jun 17 '16 at 13:10
  • @EJP All our clients only make one request at a time. E.g If a client was to collect an account number, request is read by server, server sends data response ( say an Integer ) client reads that single response and ONLY expects one response, that is it, no more data is sent by either side. I had an issue similar to this before when I wasn't setting any buffer size. Then when I set the buffer size it seemed to stop, but is now back. Do I need to add something in on the client side that sends some kind of ack back to the server and then when the server reads that it would call close? – james4563 Jun 20 '16 at 07:02
  • No. You are never closing any sockets here. Difficult to say more without seeing more code, – user207421 Jun 21 '16 at 10:01

0 Answers0