Detecting clsoed socket on OutputStream.Write

Discussion in 'Java' started by david.topham@ukgateway.net, Jun 29, 2006.

  1. Guest

    Hi

    I'm working on the client portion of a client-server app. The client
    application is fairly straightforward - it sends messages to the server
    app and blocks whilst waiting for a response. Communication in the
    client is implemented using the Java Socket class.

    In certain circumstances (that is, in response to certain messages),
    the server may terminate the socket (the server is a C app and uses
    closesocket to do this). What I'm trying to do is detect that this has
    happened when I come to send the next message. I would expect an
    IOException to be thrown from OutputStream.Write or .Flush. I can
    detect this, and then create a new socket on the client and reconnect.

    However, the exception is rarely fired, despite multiple calls to
    OutputStream.write. Instead, I get an exception on InputStream.read.

    Having looked through the archive for this group, I can see that
    similar issues to this have been raised before, although they usually
    revolve around "how do I detect when the network cable has been
    unplugged?", which seems like a different issue to me. In my case, the
    socket should have been closed on the server side, so it seems that the
    write should fail.

    In there a definitive answer to this, or is it just one of those
    vagaries of TCP/IP that we have to accept?

    Thanks

    David
     
    , Jun 29, 2006
    #1
    1. Advertising

  2. wrote:
    > Hi
    >
    > I'm working on the client portion of a client-server app. The client
    > application is fairly straightforward - it sends messages to the server
    > app and blocks whilst waiting for a response. Communication in the
    > client is implemented using the Java Socket class.
    >
    > In certain circumstances (that is, in response to certain messages),
    > the server may terminate the socket (the server is a C app and uses
    > closesocket to do this). What I'm trying to do is detect that this has
    > happened when I come to send the next message. I would expect an
    > IOException to be thrown from OutputStream.Write or .Flush. I can
    > detect this, and then create a new socket on the client and reconnect.
    >
    > However, the exception is rarely fired, despite multiple calls to
    > OutputStream.write. Instead, I get an exception on InputStream.read.
    >
    > Having looked through the archive for this group, I can see that
    > similar issues to this have been raised before, although they usually
    > revolve around "how do I detect when the network cable has been
    > unplugged?", which seems like a different issue to me. In my case, the
    > socket should have been closed on the server side, so it seems that the
    > write should fail.
    >
    > In there a definitive answer to this, or is it just one of those
    > vagaries of TCP/IP that we have to accept?
    >
    > Thanks
    >
    > David
    >


    David:

    In almost all cases when the socket is closed on the other end an
    IOException will be thrown when you write to the socket's stream. I
    have found an occasional problem that I cannot duplicate where that
    isn't true. In my case I just had a thread try to read from the socket
    to detect closure. That worked every time and solved the problem even
    if it didn't look elegant. I don't know what causes the expected
    behavior to fail.

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, Jun 29, 2006
    #2
    1. Advertising

  3. EJP Guest

    Knute Johnson wrote:
    > I don't know what causes the expected
    > behavior to fail.


    What causes this 'expected behaviour' to 'fail' is TCP asynchronous
    writing and buffering. If the write to the socket just goes into your
    local send buffer and the remote close hasn't already been detected,
    your write will succeed. It's only when you write *after* the remote
    close has been detected that you can get an IOException, and this in
    turn can only happen if there was data still pending to be written when
    the remote closure occurred.

    In practice this means doing a number of writes to provoke the
    IOException: you can't rely on a single write doing it, i.e. you can't
    rely on the *next* write getting an IOException.
     
    EJP, Jun 30, 2006
    #3
  4. EJP wrote:
    > Knute Johnson wrote:
    >> I don't know what causes the expected behavior to fail.

    >
    > What causes this 'expected behaviour' to 'fail' is TCP asynchronous
    > writing and buffering. If the write to the socket just goes into your
    > local send buffer and the remote close hasn't already been detected,
    > your write will succeed. It's only when you write *after* the remote
    > close has been detected that you can get an IOException, and this in
    > turn can only happen if there was data still pending to be written when
    > the remote closure occurred.
    >
    > In practice this means doing a number of writes to provoke the
    > IOException: you can't rely on a single write doing it, i.e. you can't
    > rely on the *next* write getting an IOException.


    That's why the read throws an exception immediately then, the outgoing
    data is locally buffered? How long will the local data be buffered?
    Does not the flush() cause it to go now?

    Thanks,

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, Jun 30, 2006
    #4
  5. EJP Guest

    Knute Johnson wrote:

    > That's why the read throws an exception immediately then, the outgoing
    > data is locally buffered? How long will the local data be buffered?
    > Does not the flush() cause it to go now?


    All that flush() does is is get it out of the JVM into the socket send
    buffer. The data can only go from there onto the wire if there is room
    in the receiver's receive buffer, and if the receiver is slower than the
    sender eventually the room will run out. Also, data is only deleted from
    the sender's send buffer once it has bene acknowledged by the receiver.
    So if the receiver completely disappears eventually your send buffer
    will fill up and eventually your TCP will time out the write attemps and
    reset the connection. Your *next* read or write will then discover this
    and get a SocketException.
     
    EJP, Jun 30, 2006
    #5
  6. EJP wrote:
    > Knute Johnson wrote:
    >
    >> That's why the read throws an exception immediately then, the outgoing
    >> data is locally buffered? How long will the local data be buffered?
    >> Does not the flush() cause it to go now?

    >
    > All that flush() does is is get it out of the JVM into the socket send
    > buffer. The data can only go from there onto the wire if there is room
    > in the receiver's receive buffer, and if the receiver is slower than the
    > sender eventually the room will run out. Also, data is only deleted from
    > the sender's send buffer once it has bene acknowledged by the receiver.
    > So if the receiver completely disappears eventually your send buffer
    > will fill up and eventually your TCP will time out the write attemps and
    > reset the connection. Your *next* read or write will then discover this
    > and get a SocketException.


    I guess I was under a misconception then, I thought if you closed a
    socket that the other end was notified of the close not that your buffer
    filled up. Is that not correct?

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, Jun 30, 2006
    #6
  7. EJP Guest

    Knute Johnson wrote:
    > I guess I was under a misconception then, I thought if you closed a
    > socket that the other end was notified of the close not that your buffer
    > filled up. Is that not correct?


    Yes, that's correct. I don't see why you think this is a misconception.
     
    EJP, Jul 1, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ryan Hartman

    large files via Response.OutputStream.Write

    Ryan Hartman, Nov 4, 2003, in forum: ASP .Net
    Replies:
    6
    Views:
    7,359
    Ryan Hartman
    Nov 11, 2003
  2. puretec

    Socket: Input/OutputStream

    puretec, Dec 22, 2004, in forum: Java
    Replies:
    0
    Views:
    325
    puretec
    Dec 22, 2004
  3. Thomas

    Socket Input-/Outputstream

    Thomas, Dec 22, 2004, in forum: Java
    Replies:
    3
    Views:
    378
    Steve Horsley
    Dec 23, 2004
  4. Replies:
    2
    Views:
    3,683
  5. Replies:
    2
    Views:
    608
Loading...

Share This Page