This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 7 years ago.
From (Java Network Programming fourth edition):
To tell if a socket is currently open, you need to
check that isConnected() returns true and isClosed() returns false. For an example:
boolean connected = socket.isConnected() && ! socket.isClosed();
I need to find a way to discover as soon as possible that the client has disconnected from the Server Socket. Using the trick described above,I have tried the following :
Socket socket = ...;
while (socket.isConnected() && !socket.isClosed()) {
// do something ...
// here, the client is always connected
}
// client is disconnected
The above approach works for me, but it is always correct?. it detects all the cases?
Depending on the application, catching exceptions intelligently would seem like a good solution. The requirement, however, is that you actually wants to send/do something to the client. Possibly a combination of the two approaches suits your specific application. You could try seeing:
Java detect lost connection
The book is wrong, if that's what it really says. isConnected() has nothing to do with whether a socket is currently open. It tells you whether it has ever been connected, which is not at all the same thing.
isOpen() does tell you whether the socket is open, but that doesn't tell you anything about the state of the connection. The test for whether the connection is still open is whether:
read() has returned -1
readLine() has returned null
readXXX() has thrown EOFException for any other X
... all of which indicate that the peer has closed the connection, or
any read or write method has thrown an IOException with the text 'connection reset'.
Related
This question already has answers here:
How to fix java.net.SocketException: Broken pipe?
(10 answers)
Closed 3 years ago.
For some of my Java NIO connections, when I have a SocketChannel.write(ByteBuffer) call, it throws an IOException: "Broken pipe".
What causes a "broken pipe", and, more importantly, is it possible to recover from that state? If it cannot be recovered, it seems this would be a good sign that an irreversible problem has occurred and that I should simply close this socket connection. Is that a reasonable assumption? Is there ever a time when this IOException would occur while the socket connection is still being properly connected in the first place (rather than a working connection that failed at some point)?
On a side note, is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write(), and if so, can I also assume that the connection is "broken" and should be closed if both SocketChannel.isConnected() and SocketChannel.isConnectionPending() are both false?
Thanks!
What causes a "broken pipe", and more importantly, is it possible to recover from that state?
It is caused by something causing the connection to close. (It is not your application that closed the connection: that would have resulted in a different exception.)
It is not possible to recover the connection. You need to open a new one.
If it cannot be recovered, it seems this would be a good sign that an irreversible problem has occurred and that I should simply close this socket connection. Is that a reasonable assumption?
Yes it is. Once you've received that exception, the socket won't ever work again. Closing it is is the only sensible thing to do.
Is there ever a time when this IOException would occur while the socket connection is still being properly connected in the first place (rather than a working connection that failed at some point)?
No. (Or at least, not without subverting proper behavior of the OS'es network stack, the JVM and/or your application.)
Is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write() ...
In general, it is a bad idea to call r.isXYZ() before some call that uses the (external) resource r. There is a small chance that the state of the resource will change between the two calls. It is a better idea to do the action, catch the IOException (or whatever) resulting from the failed action and take whatever remedial action is required.
In this particular case, calling isConnected() is pointless. The method is defined to return true if the socket was connected at some point in the past. It does not tell you if the connection is still live. The only way to determine if the connection is still alive is to attempt to use it; e.g. do a read or write.
Broken pipe simply means that the connection has failed. It is reasonable to assume that this is unrecoverable, and to then perform any required cleanup actions (closing connections, etc). I don't believe that you would ever see this simply due to the connection not yet being complete.
If you are using non-blocking mode then the SocketChannel.connect method will return false, and you will need to use the isConnectionPending and finishConnect methods to insure that the connection is complete. I would generally code based upon the expectation that things will work, and then catch exceptions to detect failure, rather than relying on frequent calls to "isConnected".
Broken pipe means you wrote to a connection that is already closed by the other end.
isConnected() does not detect this condition. Only a write does.
is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write()
It is pointless. The socket itself is connected. You connected it. What may not be connected is the connection itself, and you can only determine that by trying it.
You should assume the socket was closed on the other end. Wrap your code with a try catch block for IOException.
You can use isConnected() to determine if the SocketChannel is connected or not, but that might change before your write() invocation finishes. Try calling it in your catch block to see if in fact this is why you are getting the IOException.
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.
This question already has answers here:
Sockets: Discover port availability using Java
(10 answers)
Closed 7 years ago.
This question is about datagram socket not tcp sockets, so please review it first before thinking its duplicate Is there a way to check the port before creating a new DatagramSocket. When the port is in use for example by another instance the code below throws SocketException
socket = new DatagramSocket(4446);
I would like to have it checked before I create the DatagramSocket object. So that if it is not available I can increment it and check again untill it becomes available and then I create the Socket ?
No. Do not think that you can check all the circumstances that might cause something to fail and then be guaranteed that it will succeed. First, you'll never be able to reliably cover all the ways it can fail. Second, things can change after you test and before you operate. Instead, try to do it, and if you fail, handle the failure. If the socket construction throws an exception, then try a different port.
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.
This question already has answers here:
How to fix java.net.SocketException: Broken pipe?
(10 answers)
Closed 3 years ago.
For some of my Java NIO connections, when I have a SocketChannel.write(ByteBuffer) call, it throws an IOException: "Broken pipe".
What causes a "broken pipe", and, more importantly, is it possible to recover from that state? If it cannot be recovered, it seems this would be a good sign that an irreversible problem has occurred and that I should simply close this socket connection. Is that a reasonable assumption? Is there ever a time when this IOException would occur while the socket connection is still being properly connected in the first place (rather than a working connection that failed at some point)?
On a side note, is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write(), and if so, can I also assume that the connection is "broken" and should be closed if both SocketChannel.isConnected() and SocketChannel.isConnectionPending() are both false?
Thanks!
What causes a "broken pipe", and more importantly, is it possible to recover from that state?
It is caused by something causing the connection to close. (It is not your application that closed the connection: that would have resulted in a different exception.)
It is not possible to recover the connection. You need to open a new one.
If it cannot be recovered, it seems this would be a good sign that an irreversible problem has occurred and that I should simply close this socket connection. Is that a reasonable assumption?
Yes it is. Once you've received that exception, the socket won't ever work again. Closing it is is the only sensible thing to do.
Is there ever a time when this IOException would occur while the socket connection is still being properly connected in the first place (rather than a working connection that failed at some point)?
No. (Or at least, not without subverting proper behavior of the OS'es network stack, the JVM and/or your application.)
Is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write() ...
In general, it is a bad idea to call r.isXYZ() before some call that uses the (external) resource r. There is a small chance that the state of the resource will change between the two calls. It is a better idea to do the action, catch the IOException (or whatever) resulting from the failed action and take whatever remedial action is required.
In this particular case, calling isConnected() is pointless. The method is defined to return true if the socket was connected at some point in the past. It does not tell you if the connection is still live. The only way to determine if the connection is still alive is to attempt to use it; e.g. do a read or write.
Broken pipe simply means that the connection has failed. It is reasonable to assume that this is unrecoverable, and to then perform any required cleanup actions (closing connections, etc). I don't believe that you would ever see this simply due to the connection not yet being complete.
If you are using non-blocking mode then the SocketChannel.connect method will return false, and you will need to use the isConnectionPending and finishConnect methods to insure that the connection is complete. I would generally code based upon the expectation that things will work, and then catch exceptions to detect failure, rather than relying on frequent calls to "isConnected".
Broken pipe means you wrote to a connection that is already closed by the other end.
isConnected() does not detect this condition. Only a write does.
is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write()
It is pointless. The socket itself is connected. You connected it. What may not be connected is the connection itself, and you can only determine that by trying it.
You should assume the socket was closed on the other end. Wrap your code with a try catch block for IOException.
You can use isConnected() to determine if the SocketChannel is connected or not, but that might change before your write() invocation finishes. Try calling it in your catch block to see if in fact this is why you are getting the IOException.