Socket is closed on write stream but not when reading - java

I recently noticed in my multi threaded Java socket handler that I was getting exceptions when I tried to write on a socket, however I was still receiving data via reads. It was my understanding that if the socket was closed the input stream reader would also throw a socket closed exception when attempting the next read. Is this not the case and should I manually close the socket if I get this exception when attempting to write?

A TCP connection can be closed in the write direction but not in the read direction, such a connection is called "half closed". You should keep reading the rest of the data the other side sent, otherwise the connection will not close normally.
If you think about it, how else could you sanely shut down a TCP connection? If you shut it all the way down in one step, what happens if the other side sends some data to you before you finish shutting it down? You still need to receive it. But, obviously, you can't keep sending data.

Related

Is Socket.close() considered a clean way to end the connection?

As the title says - if I want to close a socket connection is it enough if I just call mySocket.close()? What will happen on the other side?
Or, if it's not the way to go, what is? Do I have to send some kind of "finish" message through the socket so the other side knows it should end as well?
Bonus question: java documentations says
Closing this socket will also close the socket's InputStream and OutputStream.
So is closing the socket alone enough or do I have to explicitly close the streams as well (assuming I'm not using try-with-resources, of course)?
Closing the socket won't do any thing on the other side. The remote host will not know that the connection has been closed.
The only way to check whether the connection is closed is to try to read or write from/to the input/output stream. If -1 is returned by the InputStream#read() method, then the second side knows that the first side closed the connection. A thrown IOException also indicates a closed connection.
Normally you don't need to close the in/output stream as they are closed when invoking Socket#close(). Socket#close() is the only thing you need to do to close a connection.
But if you have a wrapper stream (e.g. BufferdInputStream/BufferedOutputStream) you should explicitly close these wrapper streams to release resources used by these wrapper streams (e.g. byte buffer array). You only need to close the top level wrapper stream as closing the wrapper closes the wrapped stream which closes the wrapped stream of the wrapped stream, too. And so on...
socket.close() is a clean way to close the connection. It causes a TCP FIN packet to be sent to the peer and starts the normal TCP shutdown sequence.
It also closes the socket's InputStream and OutputStream, I don't see any ambiguity in the documentation on that point.

socket.isConnected() does not detect disconnected socket [duplicate]

This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 1 year ago.
I have a Java application that connects to a service using a socket. I always expect to receive something from that socket, and if it disconnects I need to reconnect. Reconnect works fine when I close/open socket from remote application side in normal way. But when the remote application is killed, my Java application does not detect that. I run the thread with:
if (socket.isConnected()) { /* code */ }
This function does not detect when the socket is killed. Why? How to detect that remote socket is killed?
Note: I must use java 1.4
UPD
I do reading from socket input stream acording loggic:
if (in.available()) {...}
This not detects socket is disconnected. Should I use in.read() even if no data available to detect closed socket?
The various isXXX() methods of Socket don't track the actual state, but what has been done to the socket. For example isConnected() will return true even after a socket has been closed, if it has been connected at some point.
The only way to detect if a Socket is still valid is to try to use it, i.e. read or write to it. If an exception is thrown, you need to clean up and reconnect.
This function does not detect when the socket is killed. Why?
These functions only tell you the current state of the Socket object: they don't actively test the line. isConnected() means 'have I ever connected?'.
How to detect that remote socket is killed?
You need to read a message from the connection with an appropriate timeout. If the connection is closed or lost you eventually get an IOException, or a timeout will be reached.
BTW To save error messages, I suggest you send a message indicating a graceful disconnect before closing. This way graceful disconnects can be treated differently to connection failures in term of logging.

How to tell if a socket has been disconnected (Java) [duplicate]

This question already has answers here:
How to detect a remote side socket close? [duplicate]
(4 answers)
Closed 9 years ago.
I've read several questions about this on stack overflow already, but none of them has provided me with an elegant solution.
I know that calling isConnected() and isClosed() on the Socket is useless because it returns the local connection state (if the server is connected - not if the client is connected, as I want).
I also can't simply call if(socket.getInputStream().read()==-1)* because that would only account for the end of the stream (EOS) being reached - i.e., the client didn't send a message recently. This doesn't at all indicate that the client has disconnected however.
I'm considering just having the client send a message to the server letting it know it's disconnecting just before it closes the socket, but I'm wondering if there's a simpler solution I'm missing - wanting to know the connection state of the remote socket is a fairly commonplace desire. Thanks.
*not to mention the fact that InputStream#read() is an abstract method, I'm using DataInputStream for data read methods (i.e. readInt(), readByte(), etc.)
I'm considering just having the client send a message to the server letting it know it's closing just before it closes the socket,
Why? It's pointless. You will read this message instead of getting -1 from read(). The latter is all you need. The extra read() in your post is certainly a bad idea, but the read that reads messages isn't. You need that, and you will get EOS from it. You don't need an extra message to tell you the same thing.

how to understand java remote socket is unreachable when remote socket's device is shutdowned or application force closed

I have an as3 serversocket, we are connecting to the this serversocket via java socket(an android app). The problem is that, when serversocket application force closed, i couldnt find the a way to understand that remote socket is closed or unreachable, except when trying to flush() a message to that socket throws broken pipe error. The reason that i want to solve this problem in another way is not to make server application busy with connection check messages ?
A TCP connection is not a continuous flow like a river. It's a sequence of segments sent at discrete times - thus is more like cars on a road. So there is no way to be notified if the road is broken, until a car tries to reach the other end, fails, and calls you back.
You should simply keep sending cars at reasonable intervals (30 seconds?), thus instructing your server to do nothing when it receives a NOOP message (short for No Operation). The client will be programmed to start sending NOOP when the connection is idle (no message sent or received for 30 seconds), and when the driver calls back that he can't reach his destination, you close the current socket and attempt to create another one.
There are 3 ways for TCP to understand that connection has been closed:
One side got an error - it sends a Reset request to the other side to close the connection
One side actually wants to close the connection so it sends a FIN message to the other side
A time-out when trying to transmit something from one side to another. This time-out can only happen when a tcp-package is sent. After a connection has been made , tcp's packages are only sent on a data transmitting request (and connection closing request...).
So if one side disconnects suddenly, not in middle of data transmitting, there is no way of spotting a disconnection , but to send some package once a while.
You've found the only way. TCP doesn't provide any way of checking the state of a connection other than trying to use it. You can use this more intelligently, for example you can send yourself heartbeat messages and so forth. But there is no API that will tell you.
What you can do is let the server broadcast a I am alive message every 5/10 mins :)

How to properly close a socket after an exception is caught?

After my last project I had the problem that the client was expecting an object from the server, but while processing the clients input an exception that forces the server to close the socket for security reasons is caught.
This causes the client to terminate in a very unpleasant way, the way I decided to deal with this was sending the client a Input status message after each recieved input so that he knows if his input was processed properly or if he needs to throw an exception.
So my question:
Is there a better/cleaner way to close the socket after an exception is caught?
If I understand correctly you have already closed the socket from the server side, and you need your client to realize this and handle the error accordingly.
Take a look at the Socket documentation and in particular the setSoTimeout method. For example, if the timeout is set to 5 seconds and the client attempts to read from the server socket and he does not get an answer, then the timeout expires and a java.net.SocketTimeoutException is raised and you can catch it and close the socket.
You could also use a ScheduledExecutorService or a Timer to simulate the timeout.
For things like this:
Make sure to put this socket code within a try/catch block.
Close the socket within a 'finally'. That way you ensure that you cleanly close the socket whether there is an exception or not.
Incorrect. That exception only occurs when you try to use a socket you have closed yourself.
What the OP should be looking for is EOFException, or IOException: 'connection reset', or a SocketTimeoutException.
You really can't since the socket is closed, you could listen on the client for
java.net.SocketException: socket closed
and then you would know that you lost a connection to the server.

Categories