5

the writer:

   socket.setSendBufferSize(1);
   socket.setTcpNoDelay(true);
   writer = new BufferedWriter(
          new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));

is used as follows:

try {
        writer.write(packet.toXML());
        writer.flush();
        ...
    }
    catch (Exception ioe){
        if (!done) {
            done = true;
            ... 
        }       
    }

This is client side code. When its server disconnects the socket (also java code), how come the client will only throw after 5 - 10 minutes ? Should it not throw at the first attempt to write over the dead connection ?

Thanks

Edit:

after shutting down the server, here are the TCP states:

tcp        0      0 server:443     client:50283   FIN_WAIT2 

tcp4       0      0  cient.50283     server.443       CLOSE_WAIT

Edit2:

client is an android application. Ran from phone, the second packet written causes a throw. Ran from an emulator (Mac underneath) the fourth write() will throw.

kellogs
  • 2,837
  • 3
  • 38
  • 51
  • 1
    Can you do a netstat in the command prompt and see what is the state of your TCP connection? Maybe the server wasn't able to close the connection properly yet? – Hyangelo Aug 09 '11 at 00:48
  • 2
    Is the server explicitly closing the socket, programmatically? Or are you just cutting off its network access or something like that? – Dan Aug 09 '11 at 01:02

2 Answers2

6

Should it not throw at the first attempt to write over the dead connection ?

No. All it knows is that a FIN has been received, which could have just been a shutdownOutput() by the peer - it could still be reading. So TCP has to send the data. If the peer has closed, it will issue an RST, which TCP will provide to the application on a subsequent write.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • ok, i understand this state is reached when only one side (server here) sends the FIN,ACK while the other side (cient here) does not send the same back to server. Can I somehow tweak the java client so that the TCP layer would immediately send FIN,ACK back to its server ? – kellogs Aug 09 '11 at 10:49
  • @kellogs The FIN ACK is sent when you close the socket or shut it down for output. The real point is that if you are writing to a socket that has been closed by the other end, you shouldn't be: it's an application protocol error. – user207421 Aug 09 '11 at 11:38
  • right, and I would relly like to fix that :). So i am on the client side, in java. Is there any kind of notification that java would fire upon a FIN,ACK from server ? it probably aids that the socket is being reaad through the XMPP pull parser library :-s – kellogs Aug 09 '11 at 11:56
  • @kellogs A read() would return -1, readLine() returns null, readXXX() throws EOFException for any other XXX. In TCP there is no way to detect a lost connection except via I/O. – user207421 Aug 09 '11 at 23:54
0

According to docs, readers should return -1 on read() operations, but I was not getting anything because some XmlPullparser was getting in the way

parser.setInput(connection.reader);

So, the writer behaves as EJP described above, but if you have access to source code then we could instantiate our connection.reader as some InputStreamReaderEx like so:

/** * @author kellogs * */ public class InputStreamReaderEx extends InputStreamReader {

/* (non-Javadoc)
 * @see java.io.BufferedReader#read()
 */
@Override
public int read() throws IOException {
    // TODO Auto-generated method stub
    int ret = super.read();

    if (ret == -1)
    {
        int l = 4;
    }

    return ret;
}

/* (non-Javadoc)
 * @see java.io.BufferedReader#read(char[], int, int)
 */
@Override
public int read(char[] buffer, int offset, int length) throws IOException {
    // TODO Auto-generated method stub
    int ret = super.read(buffer, offset, length);

    if (ret == -1)
    {
        int l = 4;
    }

    return ret;
}

}

and get notified when the other peer goes away

kellogs
  • 2,837
  • 3
  • 38
  • 51