Java SocketChannel doesn't detect disconnection?
Asked Answered
A

3

8

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.

Arnoldoarnon answered 14/8, 2010 at 20:24 Comment(3)
I'm confused somebody keeps changing the title of my questions. What's going on here?Arnoldoarnon
With the above code you're checking if the SocketChannel is still connected. So what exactly have you been testing, the Socket, as mentioned in your question or the channel as described in the title and shown in the code? Just asking, because people started downvoting my answer... (without explaining why...)Hecklau
1- You manually close the socket, by calling the method, that's why you get false after you disconnected from the server, in my case i am trying to detect if there was a disconnection issue, for instance "connection loss", so the socket won't detect that it's disconnected unless i try to send a message to the server and get an exception. 2- I also mentioned that i am using a selector. so isConnected method doesn't show if i am connected to the server or not, but it shows if my socket is still connected to the selector or not, which returns true as long as my socket is connected to the selectorArnoldoarnon
S
12

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.

Shankle answered 14/8, 2010 at 23:29 Comment(0)
H
7

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
Hecklau answered 14/8, 2010 at 20:49 Comment(2)
Dear downvoters - please leave a comment, if you think the answer is not helpful. At least EJP comment is incorrect as his answer... The question was about SocketChannels and I'm still sure, this explains, why turning off the airport does not result in an isConnected() == false.Hecklau
I agree with Andreas: unexplained downvotes are useless, or worse. I am coming to regard unexplained downvotes as mere site vandalism.Dupleix
D
4

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.

Dupleix answered 15/8, 2010 at 1:24 Comment(3)
isConnected() returns false on my machine when I close the channel to the remote server. See my answer for a working example.Hecklau
-1 from read doesn't work too. I added a read and it blocked (waiting for bytes). Then I pulled the network cable and the application kept blocking (no -1 as a result).Hecklau
Yes, -1 from read detects an orderly close. The only way to detect a disorderly close with a read and no writes is via a read timeout, which delivers an exception.Dupleix

© 2022 - 2024 — McMap. All rights reserved.