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

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.

Related

Socket is closed on write stream but not when reading

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.

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.

Socket not disconnecting when connectivity changes

My chat application connects to a server and information is sent/received by the user. When the connection changes, such as 3g->wifi, wifi->3g, losing a data connection, etc, the socket sometimes stays connected for ages before disconnecting. During this time, it's impossible to tell if the connection is still active, it seems as if messages are being sent just fine. Other times, when sending a message, it will throw an IO error and disconnect.
Apart from implementing code to detect connection changes and reconnecting appropriately, is it possible to have the socket immediately throw an IO exception when connectivity changes?
Edit: I'm connecting using the following code:
Socket sock = new Socket();
sock.connect(new InetSocketAddress(getAddress(), getPort())), getTimeout());
//get bufferedReader and read until BufferedReader#readLine() returns null
I'm not using setSoTimeout as data may not be transferred for long periods of time depending on the remote server's configuration.
Are you talking about a java.net.Socket connection? Then try setSoTimeout(). Otherwise specify how you're connecting.
This is an old problem that I've seen a few times before in the database world.
The solution I used there was to manage the connection at the application level. I'd explicitly send a no-op message of some sort (i.e. SELECT 1 WHERE FALSE) over the connection every so often as a ping, and if this failed I would tear down and re-establish the connection, possibly to a failover server if the original wasn't accepting connections.
As previous answers already pointed out, this is a common problem. Even after sending a custom "ping" it might need some time until the socket realizes that the underlying connection is broken. Plus, regular pings are quite energy-demanding using 3-4G mobile networks, due to their tail states. Don't do that!
What you can do, however, is requesting to get informed when the connectivity changes (last section), and close/reconnect the socket manually in the according broadcast receiver. (EDIT: I see you already found out about this; just keeping it here for completeness)

Categories