Peer2Peer NIO SelectionKey interestops(SelectionKey.OP_READ)未注册

时间:2018-06-08 13:03:22

标签: java android nio wifi-direct wifip2p

我遇到了一个问题,我的客户端(SocketChannel)没有注册OP_READ。 ServerSocketChannel之间的连接工作,当我将兴趣设置为OP_WRITE时,Selector按预期处理通道,但当我将其设置为OP_READ时,Selector.selectedKeys为空。

class ClientThread extends Thread {

  private static final String TAG = "ClientThread";

  /* Wait timeout (milliseconds) */
  private static final int TIMEOUT = 3000;

  /* The host to connect to */
  private InetAddress hostAddress;

  /* The port to listen on */
  private int port;

  /* The selector we'll be monitoring */
  private Selector selector;

  /* SocketChannel we will be listening on */
  private SocketChannel socketChannel;

  /* Run check to see if we should quit operations. */
  private volatile boolean quit;

  /* Buffer to read on */
  private ByteBuffer readBuffer = ByteBuffer.allocate(BUF_SIZE);

  public ClientThread(InetAddress hostAddress, int port)
      throws IOException {
    this.hostAddress = hostAddress;
    this.port = port;
  }

  /**
   * Quit all pending operations on this thread.
   *
   * <p>See:
   * https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
   */
  void quit() {
    this.quit = true;
    interrupt();
  }

  public void run() {
    // We want a background thread.
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

    try {

      // Create a non-blocking socket channel
      socketChannel = SocketChannel.open();
      selector = Selector.open();
      socketChannel.configureBlocking(false);

      // Kick off connection establishment
      socketChannel.connect(new InetSocketAddress(this.hostAddress, this.port));

      // Register Selector
      socketChannel.register(selector, SelectionKey.OP_CONNECT);

      Log.v(TAG, "SocketChannel connected");

      while (true) {

        // Check if the thread needs to be killed.
        if (quit) {
          selector.close();
          socketChannel.close();
          selector = null;
          socketChannel = null;
          return;
        }


        // Wait for a channel to be ready.
        // Wait for a channel to be ready.
        if (selector.select(TIMEOUT) == 0) { // returns # of ready chans
          Log.v(TAG, "waiting for connection");
          continue;
        }

        Log.v(TAG, "SocketChannel ready");

        // Iterate over the set of keys for which events are available
        Iterator selectedKeys = selector.selectedKeys().iterator();
        while (selectedKeys.hasNext()) {

          SelectionKey key = (SelectionKey) selectedKeys.next();
          selectedKeys.remove();
          Log.v(TAG, "SelectionKey: " + SelectionKeyUtil.readableSelectionKey(key));

          if (!key.isValid()) {
            Log.v(TAG, "key isInvalid");
            continue;
          }

          // Check what event is available and deal with it
          if (key.isConnectable()) {
            this.handleConnection(key);
          } else if (key.isReadable()) {
            this.handleRead(key);
          } 
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      socketChannel = null;
      selector = null;
      hostAddress = null;
    }
  }

  public void handleConnection(SelectionKey key) throws IOException {
    // Finish the connection. If the connection operation failed an IOException will occur.
    SocketChannel socketChannel = (SocketChannel) key.channel();

    try {
      boolean connected = socketChannel.finishConnect();

      Log.v(TAG, "SocketChannel connection finished: " + connected);
    } catch (IOException e) {
      // Cancel the channel's registration with the selector.
      e.printStackTrace();
      key.cancel();
      return;
    }

    // Register an interest in reading on this channel
    SelectionKey key = socketChannel.keyFor(selector);
    key.interestOps(SelectionKey.OP_READ);
  }


  public void handleRead(SelectionKey key) throws IOException {
    // Client socket channel has pending data.
    socketChannel = (SocketChannel) key.channel();
    readBuffer.clear(); // Prepare buffer for input, ignoring existing state

    long bytesRead = socketChannel.read(readBuffer);
    if (bytesRead == -1) { // Client maybe closed
      socketChannel.close();
    } else if (bytesRead > 0) {

      Log.v(TAG, "Read bytes available");
    }
  }
}

任何帮助都会很棒。

0 个答案:

没有答案