Detecting clsoed socket on OutputStream.Write

D

david.topham

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
 
K

Knute Johnson

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.
 
E

EJP

Knute said:
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.
 
K

Knute Johnson

EJP said:
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,
 
E

EJP

Knute said:
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.
 
K

Knute Johnson

EJP said:
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?
 
E

EJP

Knute said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top