private void _connect(Dictionary <string, string> data = null) { for (int i = 0; i < _ipAddresses.Count; i++) { try { // if the IP address is not supported then skip, e.g. IPv6 address but not supported by network card if (_ipAddresses[i] == null || (_ipAddresses[i].AddressFamily == AddressFamily.InterNetwork && !Socket.OSSupportsIPv4) || (_ipAddresses[i].AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6)) { continue; } // attempt to connect to remote endpoint (will throw if not available) _tcpClient = ComponentFactory.BuildTcpClient(_ipAddresses[i].ToString(), _port, _sslSettings); _networkStream = _tcpClient.GetStream(); _networkStream.AuthenticateAsClient(); Log.InfoFormat("[{0}] Connected to {1}:{2}", ID, _ipAddresses[i], _port); break; } catch (Exception e) { Log.ErrorFormat($"Unable to connect to remote endpoint: {e.Message}"); _tcpClient = null; _networkStream = null; } } // did one of the addresses make a connection if (_tcpClient != null && _networkStream != null) { // create and start the frame decoder _streamDecoderTask = _decodeStreamAsync(_networkStream, _cts.Token); // update state and send start frame State = ConnectionState.ConnectionStartSent; _sendFrame(FrameType.ConnectionStart, Frame.CreateConnectionStartFrame(data)); // block until the connection is established, errors, or times out var index = WaitHandle.WaitAny(new[] { _connectionOpen, _connectionError }, 2000); // what was the result? switch (index) { // success - return the established connection case 0: return; // the connection failed case 1: throw new ConnectionException("Unable to establish connection"); // establishing the connection timed out case WaitHandle.WaitTimeout: throw new ConnectionTimeoutException("Establishing a conneciton the remote endpoint timed out"); // should never each this point default: throw new Exception(); } } else { // failed to connect to the remote endpoint throw new ConnectionException("Unable to establish connection"); } }