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);
      }
    }
  }