@Override
  protected void registerTask(AbstractNioChannel channel, ChannelFuture future) {
    final SocketAddress localAddress = channel.getLocalAddress();
    if (localAddress == null) {
      if (future != null) {
        future.setFailure(new ClosedChannelException());
      }
      close(channel, succeededFuture(channel));
      return;
    }

    try {
      synchronized (channel.interestOpsLock) {
        channel.getJdkChannel().register(selector, channel.getRawInterestOps(), channel);
      }
      if (future != null) {
        future.setSuccess();
      }
    } catch (final ClosedChannelException e) {
      if (future != null) {
        future.setFailure(e);
      }
      close(channel, succeededFuture(channel));
      throw new ChannelException("Failed to register a socket to the selector.", e);
    }
  }
  @Override
  public void writeFromUserCode(final AbstractNioChannel channel) {
    /*
     * Note that we are not checking if the channel is connected. Connected
     * has a different meaning in UDP and means that the channels socket is
     * configured to only send and receive from a given remote peer.
     */
    if (!channel.isBound()) {
      cleanUpWriteBuffer(channel);
      return;
    }

    if (scheduleWriteIfNecessary(channel)) {
      return;
    }

    // From here, we are sure Thread.currentThread() == workerThread.

    if (channel.writeSuspended) {
      return;
    }

    if (channel.inWriteNowLoop) {
      return;
    }

    write0(channel);
  }
 /**
  * Writes the outgoing {@link DatagramPacket} to the channel. The intended receiver of the
  * datagram packet must be set in the <code>data</code> using {@link
  * DatagramPacket#setReceiver(SocketAddress)}.
  */
 @Override
 public void write(Object data, SelectionKey key) {
   super.write(data, key);
 }
  @Override
  protected void write0(final AbstractNioChannel channel) {

    boolean addOpWrite = false;
    boolean removeOpWrite = false;

    long writtenBytes = 0;

    final SendBufferPool sendBufferPool = this.sendBufferPool;
    final DatagramChannel ch = ((NioDatagramChannel) channel).getJdkChannel().getChannel();
    final Queue<MessageEvent> writeBuffer = channel.writeBufferQueue;
    final int writeSpinCount = channel.getConfig().getWriteSpinCount();
    synchronized (channel.writeLock) {
      // inform the channel that write is in-progress
      channel.inWriteNowLoop = true;

      // loop forever...
      for (; ; ) {
        MessageEvent evt = channel.currentWriteEvent;
        SendBuffer buf;
        if (evt == null) {
          if ((channel.currentWriteEvent = evt = writeBuffer.poll()) == null) {
            removeOpWrite = true;
            channel.writeSuspended = false;
            break;
          }

          channel.currentWriteBuffer = buf = sendBufferPool.acquire(evt.getMessage());
        } else {
          buf = channel.currentWriteBuffer;
        }

        try {
          long localWrittenBytes = 0;
          SocketAddress raddr = evt.getRemoteAddress();
          if (raddr == null) {
            for (int i = writeSpinCount; i > 0; i--) {
              localWrittenBytes = buf.transferTo(ch);
              if (localWrittenBytes != 0) {
                writtenBytes += localWrittenBytes;
                break;
              }
              if (buf.finished()) {
                break;
              }
            }
          } else {
            for (int i = writeSpinCount; i > 0; i--) {
              localWrittenBytes = buf.transferTo(ch, raddr);
              if (localWrittenBytes != 0) {
                writtenBytes += localWrittenBytes;
                break;
              }
              if (buf.finished()) {
                break;
              }
            }
          }

          if (localWrittenBytes > 0 || buf.finished()) {
            // Successful write - proceed to the next message.
            buf.release();
            ChannelFuture future = evt.getFuture();
            channel.currentWriteEvent = null;
            channel.currentWriteBuffer = null;
            evt = null;
            buf = null;
            future.setSuccess();
          } else {
            // Not written at all - perhaps the kernel buffer is full.
            addOpWrite = true;
            channel.writeSuspended = true;
            break;
          }
        } catch (final AsynchronousCloseException e) {
          // Doesn't need a user attention - ignore.
        } catch (final Throwable t) {
          buf.release();
          ChannelFuture future = evt.getFuture();
          channel.currentWriteEvent = null;
          channel.currentWriteBuffer = null;
          buf = null;
          evt = null;
          future.setFailure(t);
          fireExceptionCaught(channel, t);
        }
      }
      channel.inWriteNowLoop = false;

      // Initially, the following block was executed after releasing
      // the writeLock, but there was a race condition, and it has to be
      // executed before releasing the writeLock:
      //
      // https://issues.jboss.org/browse/NETTY-410
      //
      if (addOpWrite) {
        setOpWrite(channel);
      } else if (removeOpWrite) {
        clearOpWrite(channel);
      }
    }

    Channels.fireWriteComplete(channel, writtenBytes);
  }