Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java SocketChannel doesn't detect disconnection?

I have a socket running, using selectors. I am trying to check to see if my socket is connected to the server or not.

Boolean connected = _channel.isConnected();

and it always returns true. I turned off Airport (internet connection) on my computer, and when i check to see if the socket is connected or not, it still returns true. Any idea why? I try to write data to the server every 3 seconds, and it still doesn't change the state of my socket to disconnected.

like image 752
aryaxt Avatar asked Aug 14 '10 20:08

aryaxt


3 Answers

Usually if you turn off OS level networking, writes to socket should throw exceptions, so you know the connection is broken.

However more generally, we cann't be sure if a packet is delivered. In java (probably C too), there is no way to check if a packet is ACK'ed.

Even if we can check TCP ACKs, it doesn't guarantee that the server received or processed the packet. It only means that the target machine received the packet and buffered it in memory. Many things can go wrong after that.

So if you really want to sure, you can't rely on transport protocol. You must have application level ACK, that is, the server application writes back an ACK message after it received and processed a message from client.

From client point of view, it writes a message to server, then tries to read ACK from server. If it gets it, it can be certain that its message is received and processed. If it fails to get ACK, well, it has no idea what has happened. Empirically, most likely TCP failed. Next possiblity is that server crashed. It's also possible that everything went OK, except the ACK couldn't reach the client.

like image 96
irreputable Avatar answered Oct 17 '22 02:10

irreputable


A socket channel can be connected by invoking its connect method; once connected, a socket channel remains connected until it is closed.

The channel is not closed when the server is not available anymore, due to a broken physical connection or a server failure. So once a connection has been established, isConnected() will be returning true until you close the channel on your side.

If you want to check, if the server is still available, send a byte to the sockets outputstream. If you get an Exception, then the server is unavailable (connection lost).


Edit

for EJP - some code to test and reconsider your comment and answer:

public class ChannelTest {
     public static void main(String[] args) throws UnknownHostException, IOException {
      Socket google = new Socket(InetAddress.getByName("www.google.com"), 80);
      SocketChannel channel = SocketChannel.open(google.getRemoteSocketAddress());
      System.out.println(channel.isConnected());
      channel.close();
      System.out.println(channel.isConnected());
    }
}

Output on my machine is

true
false
like image 28
Andreas Dolk Avatar answered Oct 17 '22 01:10

Andreas Dolk


isConnected() tells you whether you have connected the channel object, which you have, and it's not specified to return false after you close it, although apparently it does: see Andreas's answer. It's not there to tell you whether the underlying connection is still there. You can only tell that by using it: -1 from a read, or an exception, tells you that.

like image 4
user207421 Avatar answered Oct 17 '22 03:10

user207421