使用非阻塞的SocketChannel,是附属的Socket阻塞吗?

时间:2011-07-20 23:07:25

标签: android sockets io nonblocking socketchannel

我正在开发一个Android应用程序,尝试从套接字上的一个线程执行非阻塞写入,同时在另一个线程上执行阻塞读取。我正在查看SocketChannel文档,并试图弄清楚configureBlocking究竟是做什么的。具体来说,如果我有一个非阻塞的SocketChannel,并且我使用socketChannel.socket()访问附属的Socket,那么Socket在某种程度上也是非阻塞的吗?还是阻止?

换句话说,通过为非阻塞方向设置非阻塞SocketChannel,并将附属Socket用于其他方向,我可以获得一个阻塞方向和一个非阻塞方向的效果吗?

1 个答案:

答案 0 :(得分:0)

如果Socket有关联的SocketChannel,则无法直接从InputStream读取。你会得到IllegalBlockingModeException。请参阅here

您可以registering阻止非阻塞的SocketChannel使用Selector并使用select()select(long timeout)。这些方法通常会阻塞,直到注册的通道准备就绪(或超时到期)。

对于不使用选择器的线程,通道仍然是非阻塞的。

来自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
    }
  }
}