3

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);
}
Falkon
  • 41
  • 5

2 Answers2

1

" 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

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • I was talking of the message. I'm using my own protocol where after client set the TCP comunication with the server, client send some bytes via socketchannel with the first byte used to identify a specific request so server understand what type of request the client is asking for. in a similar manner server send bytes to client – Falkon Feb 28 '20 at 16:22
0

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!");
     }
}
s.fuhrm
  • 438
  • 4
  • 9
  • So I will never get 0 if the key of the socketChannel is selected! This explains all. Thanks :) – Falkon Feb 28 '20 at 16:12
  • To speak defensively, not necessarily. But you have a good chance to get more than 0 most of the time. :-) – s.fuhrm Feb 29 '20 at 14:28