private void processKey(SelectionKey key) {

    try {

      if (key.isReadable()) {
        final DatagramChannel socketChannel = (DatagramChannel) key.channel();
        reader.readAll(socketChannel);
      }

      if (key.isWritable()) {
        final DatagramChannel socketChannel = (DatagramChannel) key.channel();
        try {
          int bytesJustWritten = writer.writeAll(socketChannel);
          contemplateThrottleWrites(bytesJustWritten);
        } catch (NotYetConnectedException e) {
          if (LOG.isDebugEnabled()) LOG.debug("", e);
          serverConnector.connectLater();
        } catch (IOException e) {
          if (LOG.isDebugEnabled()) LOG.debug("", e);
          serverConnector.connectLater();
        }
      }
    } catch (Exception e) {
      LOG.error("", e);
      if (!isClosed) closeEarlyAndQuietly(key.channel());
    }
  }
  /** binds to the server socket and process data This method will block until interrupted */
  @Override
  void processEvent() throws IOException {
    try {

      connectClient().register(selector, OP_READ);
      serverConnector.connectLater();

      while (selector.isOpen()) {
        registerPendingRegistrations();

        // this may block for a long time, upon return the
        // selected set contains keys of the ready channels
        final int n = selector.select(100);

        if (shouldEnableOpWrite) enableWrites();

        checkThrottleInterval();

        if (n == 0) {
          continue; // nothing to do
        }

        if (useJavaNIOSelectionKeys) {
          // use the standard java nio selector

          final Set<SelectionKey> selectionKeys = selector.selectedKeys();
          for (final SelectionKey key : selectionKeys) {
            processKey(key);
          }
          selectionKeys.clear();
        } else {
          // use the netty like selector

          final SelectionKey[] keys = selectedKeys.flip();

          try {
            for (int i = 0; i < keys.length && keys[i] != null; i++) {
              final SelectionKey key = keys[i];

              try {
                processKey(key);
              } catch (BufferUnderflowException e) {
                if (!isClosed) LOG.error("", e);
              }
            }
          } finally {
            for (int i = 0; i < keys.length && keys[i] != null; i++) {
              keys[i] = null;
            }
          }
        }
      }
    } catch (CancelledKeyException
        | ConnectException
        | ClosedChannelException
        | ClosedSelectorException e) {
      if (LOG.isDebugEnabled()) LOG.debug("", e);
    } catch (Exception e) {
      LOG.error("", e);
    } catch (Throwable e) {
      LOG.error("", e);
      throw e;
    } finally {

      if (LOG.isDebugEnabled()) LOG.debug("closing name=" + this.name);
      if (!isClosed) {
        closeResources();
      }
    }
  }