How can I test if a SocketChannel.read() for a non-blocking channel has finished?

Viewed 655

I'm using a function to read bytes from non-blocking SocketChannel (socket from accept()) and from blocking SocketChannel (client side). I'm implementing a server using selector to handle multiple clients, and I'm using loopback address to use my laptop only. I wrote this

while((r = socketChannel.read(ackBuf)) != -1) {
        System.out.println(name3d+" r: "+r);
    }

and I expected that when the end of the content in the channel was reached, read() would returned -1 but is not what succedes. read(), in non-blocking configuration, return 0 also if nothing is ready to read at the moment but it will be soon (if I understand well) so if I change the code to

while((r = socketChannel.read(ackBuf)) > 0) {
        System.out.println(name3d+" r: "+r);
    }

I will not read nothing also if something will be ready a moment later. How can I distinguish if I got 0 because is not ready or because it is ended? In the following snippet I can test for a second time the read after a sleep but I'm sure is not the reliable way to do what I want.

int times = 0;
while((r = socketChannel.read(ackBuf)) != -1 && times<2) {
    if (r == 0)
        try {
            Thread.sleep(500);
            times++;
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    System.out.println(name3d+" r: "+r);
}
2 Answers

" if I got 0 because is not ready or because it is ended?" Do you mean the message or the totality of the communication?

For the message, you should use a communication protocol (like json or http) for the communication, I think you should get a SocketException... You would if you using blocking and the person on the other end closed the connection... (I've written to a lot of people on SO about how SocketException is your friend)

--- edit ---

Looking over the documention for Channel, it looks like you should get an IOException of some kind (SocketException is a subclass of IOException) if/when the channcel is closed

The Non-blocking SocketChannel is used a bit different.

  1. You first wait for the selection key to tell you that there is data, and
  2. then you read that data from the channel.

See this code draft:

  Selector selector = Selector.open();
  SocketChannel sc = SocketChannel.open();
  sc.configureBlocking(false);
  sc.connect(addr);
  sc.register(selector, SelectionKey.OP_READ);
  while (true) {
    // select() can block!
    if (selector.select() == 0) {
      continue;
    }
    Iterator iterator = selector.selectedKeys().iterator();
    while (iterator.hasNext()) {
     SelectionKey key = (SelectionKey) iterator.next();
     iterator.remove();
     if (key.isReadable()) {
       SocketChannel sc = (SocketChannel) key.channel();
       ByteBuffer bb = ByteBuffer.allocate(1024);
       sc.read(bb);
       System.out.println("Message received!");
     }
}
Related