1
votes

I'm developing an Android app, trying to do a non-blocking write from one thread on a socket, while doing a blocking read on another thread. I'm looking through SocketChannel docs and trying to figure out what exactly configureBlocking does. Specifically, if I have a non-blocking SocketChannel, and I access the affiliated Socket with socketChannel.socket(), is that Socket also non-blocking in some way? Or is it blocking?

In other words, can I get the effect of one blocking direction and one non-blocking direction by having a non-blocking SocketChannel for the non-blocking direction, and using the affiliated Socket for the other direction?

1

1 Answers

0
votes

If the Socket has an associated SocketChannel, you cannot directly read from it's InputStream. You'll get IllegalBlockingModeException. See here.

You can block on non-blocking SocketChannels by registering them to a Selector and using select() or select(long timeout). Those methods usually block until a registered channel is ready (or the timeout expired).

The channel is still non-blocking for threads not using a selector.

Modified example from here:

Selector selector = Selector.open();
channel.configureBlocking(false);

// register for OP_READ: you are interested in reading from the channel
channel.register(selector, SelectionKey.OP_READ);

while (true) {
  int readyChannels = selector.select(); // This one blocks...

  // Safety net if the selector awoke by other means
  if (readyChannels == 0) continue;

  Set<SelectionKey> selectedKeys = selector.selectedKeys();
  Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

  while (keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();

    keyIterator.remove();

    if (!key.isValid()) {
      continue;
    } else if (key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.
    } else if (key.isConnectable()) {
        // a connection was established with a remote server.
    } else if (key.isReadable()) {
        // a channel is ready for reading
    } else if (key.isWritable()) {
        // a channel is ready for writing
    }
  }
}