/// <exception cref="System.IO.IOException"></exception>
        public ClientConnection(ClientConnectionManager clientConnectionManager,
            ClientInvocationService invocationService,
            int id,
            Address address,
            ClientNetworkConfig clientNetworkConfig)
        {
            _clientConnectionManager = clientConnectionManager;
            _id = id;

            var isa = address.GetInetSocketAddress();
            var socketOptions = clientNetworkConfig.GetSocketOptions();
            var socketFactory = socketOptions.GetSocketFactory() ?? new DefaultSocketFactory();
            _clientSocket = socketFactory.CreateSocket();

            try
            {
                _clientSocket = new Socket(isa.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                var lingerOption = new LingerOption(true, 5);
                if (socketOptions.GetLingerSeconds() > 0)
                {
                    lingerOption.LingerTime = socketOptions.GetLingerSeconds();
                }
                _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
                _clientSocket.NoDelay = socketOptions.IsTcpNoDelay();

                _clientSocket.ReceiveTimeout = socketOptions.GetTimeout() > 0 ? socketOptions.GetTimeout() : -1;

                var bufferSize = socketOptions.GetBufferSize() * 1024;
                if (bufferSize < 0)
                {
                    bufferSize = BufferSize;
                }

                _clientSocket.SendBufferSize = bufferSize;
                _clientSocket.ReceiveBufferSize = bufferSize;

                var connectionTimeout = clientNetworkConfig.GetConnectionTimeout() > -1
                    ? clientNetworkConfig.GetConnectionTimeout()
                    : ConnectionTimeout;
                var socketResult = _clientSocket.BeginConnect(address.GetHost(), address.GetPort(), null, null);

                if (!socketResult.AsyncWaitHandle.WaitOne(connectionTimeout, true) || !_clientSocket.Connected)
                {
                    // NOTE, MUST CLOSE THE SOCKET
                    _clientSocket.Close();
                    throw new IOException("Failed to connect to " + address);
                }
                _sendBuffer = ByteBuffer.Allocate(BufferSize);
                _receiveBuffer = ByteBuffer.Allocate(BufferSize);

                _builder = new ClientMessageBuilder(invocationService.HandleClientMessage);

                var networkStream = new NetworkStream(_clientSocket, false);
                if (clientNetworkConfig.GetSSLConfig().IsEnabled())
                {
                    var sslStream = new SslStream(networkStream, false,
                        (sender, certificate, chain, sslPolicyErrors) =>
                            RemoteCertificateValidationCallback(sender, certificate, chain, sslPolicyErrors,
                                clientNetworkConfig), null);
                    var certificateName = clientNetworkConfig.GetSSLConfig().GetCertificateName() ?? "";
                    sslStream.AuthenticateAsClient(certificateName);
                    _stream = sslStream;
                }
                else
                {
                    _stream = networkStream;
                }
                _live = new AtomicBoolean(true);
            }
            catch (Exception e)
            {
                _clientSocket.Close();
                if (_stream != null)
                {
                    _stream.Close();
                }
                throw new IOException("Cannot connect! Socket error:" + e.Message);
            }
        }
        /// <exception cref="System.IO.IOException"></exception>
        public ClientConnection(ClientConnectionManager clientConnectionManager,
            ClientInvocationService invocationService,
            int id,
            Address address,
            ClientNetworkConfig clientNetworkConfig)
        {
            _clientConnectionManager = clientConnectionManager;
            _id = id;

            var isa = address.GetInetSocketAddress();
            var socketOptions = clientNetworkConfig.GetSocketOptions();
            var socketFactory = socketOptions.GetSocketFactory();

            if (socketFactory == null)
            {
                socketFactory = new DefaultSocketFactory();
            }
            _clientSocket = socketFactory.CreateSocket();
            try
            {
                _clientSocket = new Socket(isa.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                var lingerOption = new LingerOption(true, 5);
                if (socketOptions.GetLingerSeconds() > 0)
                {
                    lingerOption.LingerTime = socketOptions.GetLingerSeconds();
                }
                _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
                _clientSocket.NoDelay = socketOptions.IsTcpNoDelay();

                _clientSocket.ReceiveTimeout = socketOptions.GetTimeout() > 0 ? socketOptions.GetTimeout() : -1;

                var bufferSize = socketOptions.GetBufferSize()*1024;
                if (bufferSize < 0)
                {
                    bufferSize = BufferSize;
                }

                _clientSocket.SendBufferSize = bufferSize;
                _clientSocket.ReceiveBufferSize = bufferSize;

                _clientSocket.UseOnlyOverlappedIO = true;

                var connectionTimeout = clientNetworkConfig.GetConnectionTimeout() > -1
                    ? clientNetworkConfig.GetConnectionTimeout()
                    : ConnectionTimeout;
                var socketResult = _clientSocket.BeginConnect(address.GetHost(), address.GetPort(), null, null);

                if (!socketResult.AsyncWaitHandle.WaitOne(connectionTimeout, true) || !_clientSocket.Connected)
                {
                    // NOTE, MUST CLOSE THE SOCKET
                    _clientSocket.Close();
                    throw new IOException("Failed to connect to " + address);
                }
                _sendBuffer = ByteBuffer.Allocate(BufferSize);
                _receiveBuffer = ByteBuffer.Allocate(BufferSize);

                _builder = new ClientMessageBuilder(invocationService.HandleClientMessage);

                _live = true;
            }
            catch (Exception e)
            {
                _clientSocket.Close();
                throw new IOException("Cannot connect! Socket error:" + e.Message);
            }
        }