final Duration writeTimeout,
            final int maxFrameSize,
            final String clientName,
            HostAndPort socksProxy)
    {
        NiftyClientChannel channel = null;
        try {
            final SettableFuture<T> clientFuture = SettableFuture.create();
            ListenableFuture<C> connectFuture =
                    niftyClient.connectAsync(connector,
                                             connectTimeout,
                                             readTimeout,
                                             writeTimeout,
                                             maxFrameSize,
                                             this.toSocksProxyAddress(socksProxy));
            Futures.addCallback(connectFuture, new FutureCallback<C>()
            {
                @Override
                public void onSuccess(C result)
                {
                    NiftyClientChannel channel = result;
                    if (readTimeout.toMillis() > 0) {
                        channel.setReceiveTimeout(readTimeout);
                    }
                    if (writeTimeout.toMillis() > 0) {
                        channel.setSendTimeout(writeTimeout);
                    }
                    clientFuture.set(createClient(channel, type, Strings.isNullOrEmpty(clientName) ? connector.toString() : clientName));
                }
                @Override
                public void onFailure(Throwable t)
                {
                    clientFuture.setException(t);
                }
            });
            return clientFuture;
        }
        catch (RuntimeException | Error e) {
            if (channel != null) {
                channel.close();
            }
            throw e;
        }
    }