/**
   * Will bind the DatagramSocket to the passed-in address. Every call bind will spawn a new thread
   * using the that basically in turn
   */
  private void bind(
      final NioDatagramChannel channel,
      final ChannelFuture future,
      final InetSocketAddress address) {
    boolean bound = false;
    boolean started = false;
    try {
      // First bind the DatagramSocket the specified port.
      channel.getDatagramChannel().socket().bind(address);
      bound = true;

      future.setSuccess();
      fireChannelBound(channel, address);

      channel.worker.register(channel, null);
      started = true;
    } catch (final Throwable t) {
      future.setFailure(t);
      fireExceptionCaught(channel, t);
    } finally {
      if (!started && bound) {
        close(channel, future);
      }
    }
  }
 private void close(NioDatagramChannel channel, ChannelFuture future) {
   try {
     channel.getDatagramChannel().socket().close();
     if (channel.setClosed()) {
       future.setSuccess();
       if (channel.isBound()) {
         fireChannelUnbound(channel);
       }
       fireChannelClosed(channel);
     } else {
       future.setSuccess();
     }
   } catch (final Throwable t) {
     future.setFailure(t);
     fireExceptionCaught(channel, t);
   }
 }
  private void connect(
      NioDatagramChannel channel, ChannelFuture future, SocketAddress remoteAddress) {

    boolean bound = channel.isBound();
    boolean connected = false;
    boolean workerStarted = false;

    future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);

    // Clear the cached address so that the next getRemoteAddress() call
    // updates the cache.
    channel.remoteAddress = null;

    try {
      channel.getDatagramChannel().connect(remoteAddress);
      connected = true;

      // Fire events.
      future.setSuccess();
      if (!bound) {
        fireChannelBound(channel, channel.getLocalAddress());
      }
      fireChannelConnected(channel, channel.getRemoteAddress());

      if (!bound) {
        channel.worker.register(channel, future);
      }

      workerStarted = true;
    } catch (Throwable t) {
      future.setFailure(t);
      fireExceptionCaught(channel, t);
    } finally {
      if (connected && !workerStarted) {
        channel.worker.close(channel, future);
      }
    }
  }