private void OpenSocket(object state) { int connectionAttempts = 0; while (MaxConnectionAttempts == -1 || connectionAttempts < MaxConnectionAttempts) { if ((object)m_zeroMQClient.Provider != null) { // Disconnect any existing ZeroMQ socket try { m_zeroMQClient.Provider.Disconnect(ServerUri); } catch (Exception ex) { OnDisconnectException(ex); } m_zeroMQClient.Reset(); } try { OnConnectionAttempt(); // Create ZeroMQ Dealer socket - closest match to IClient implementation m_zeroMQClient.Provider = new ZSocket(ZContext.Create(), ZSocketType.DEALER); m_zeroMQClient.Provider.Identity = m_zeroMQClient.ID.ToByteArray(); m_zeroMQClient.Provider.SendHighWatermark = m_maxSendQueueSize; m_zeroMQClient.Provider.ReceiveHighWatermark = m_maxReceiveQueueSize; m_zeroMQClient.Provider.Immediate = true; m_zeroMQClient.Provider.SetOption(ZSocketOption.LINGER, 0); m_zeroMQClient.Provider.SetOption(ZSocketOption.SNDTIMEO, 1000); m_zeroMQClient.Provider.SetOption(ZSocketOption.RCVTIMEO, -1); m_zeroMQClient.Provider.SetOption(ZSocketOption.RECONNECT_IVL, -1); m_zeroMQClient.Provider.IPv6 = (Transport.GetDefaultIPStack() == IPStack.IPv6); m_zeroMQClient.Provider.Connect(ServerUri); m_connectionHandle.Set(); connectionAttempts = 0; OnConnectionEstablished(); } catch (Exception ex) { m_zeroMQClient.Provider = null; // Log exception during connection attempt OnConnectionException(ex); // Keep retrying connection Thread.Sleep(1000); connectionAttempts++; continue; } try { // Start data reception loop ReceiveDataHandler(); } catch (Exception ex) { // Notify of the exception. OnReceiveDataException(ex); } // If client is no longer connected, exit loop, else sleep for a moment before attempting reconnect if (Enabled) { Thread.Sleep(1000); } else { break; } } }
/// <summary> /// Validates the specified <paramref name="connectionString"/>. /// </summary> /// <param name="connectionString">Connection string to be validated.</param> /// <exception cref="ArgumentException">Server property is missing.</exception> /// <exception cref="FormatException">Server property is invalid.</exception> /// <exception cref="ArgumentOutOfRangeException">Server port value is not between <see cref="Transport.PortRangeLow"/> and <see cref="Transport.PortRangeHigh"/>.</exception> protected override void ValidateConnectionString(string connectionString) { m_connectData = connectionString.ParseKeyValuePairs(); // Make sure "interface" setting exists Transport.GetInterfaceIPStack(m_connectData); // Check if 'server' property is missing. if (!m_connectData.ContainsKey("server")) { throw new ArgumentException(string.Format("Server property is missing (Example: {0})", DefaultConnectionString)); } // Backwards compatibility adjustments. // New Format: Server=localhost:8888 // Old Format: Server=localhost; Port=8888 if (m_connectData.ContainsKey("port")) { m_connectData["server"] = string.Format("{0}:{1}", m_connectData["server"], m_connectData["port"]); } // For traditional style connection strings, also support a "zeroMQTransportProtocol" setting if (m_connectData.ContainsKey("zeroMQTransportProtocol")) { ZeroMQTransportProtocol protocol; if (Enum.TryParse(m_connectData["zeroMQTransportProtocol"].Trim(), true, out protocol)) { m_zeroMQTransportProtocol = protocol; } } // Validate ZeroMQ connection string Match endpointMatch = Regex.Match(m_connectData["server"], ZeroMQServer.EndpointFormatRegex); string port = null; bool validConnectionString = false; if (endpointMatch.Success) { if (!Enum.TryParse(endpointMatch.Groups["protocol"].Value.Trim(), true, out m_zeroMQTransportProtocol)) { m_zeroMQTransportProtocol = ZeroMQTransportProtocol.Tcp; } port = endpointMatch.Groups["port"].Value.Trim(); validConnectionString = true; if (!string.IsNullOrWhiteSpace(m_connectData["interface"]) && (m_zeroMQTransportProtocol == ZeroMQTransportProtocol.Pgm || m_zeroMQTransportProtocol == ZeroMQTransportProtocol.Epgm)) { m_connectData["server"] = string.Format("{0}://{1};{2}:{3}", m_zeroMQTransportProtocol.ToString().ToLowerInvariant(), m_connectData["interface"], endpointMatch.Groups["host"].Value.Trim(), port); } } else { // Support traditional IClient "server" property endpointMatch = Regex.Match(m_connectData["server"], Transport.EndpointFormatRegex); if (endpointMatch.Success) { m_connectData["server"] = string.Format("{0}://{1}", m_zeroMQTransportProtocol.ToString().ToLowerInvariant(), m_connectData["server"]); port = endpointMatch.Groups["port"].Value.Trim(); validConnectionString = true; if (!string.IsNullOrWhiteSpace(m_connectData["interface"]) && (m_zeroMQTransportProtocol == ZeroMQTransportProtocol.Pgm || m_zeroMQTransportProtocol == ZeroMQTransportProtocol.Epgm)) { m_connectData["server"] = string.Format("{0}://{1};{2}:{3}", m_zeroMQTransportProtocol.ToString().ToLowerInvariant(), m_connectData["interface"], endpointMatch.Groups["host"].Value.Trim(), port); } } } if (!validConnectionString) { throw new FormatException(string.Format("Server property is invalid (Example: {0})", DefaultConnectionString)); } if (m_zeroMQTransportProtocol != ZeroMQTransportProtocol.InProc && !Transport.IsPortNumberValid(port)) { throw new ArgumentOutOfRangeException("connectionString", string.Format("Server port must between {0} and {1}", Transport.PortRangeLow, Transport.PortRangeHigh)); } }
/// <summary> /// Validates the specified <paramref name="configurationString"/>. /// </summary> /// <param name="configurationString">Configuration string to be validated.</param> /// <exception cref="ArgumentException">Port property is missing.</exception> /// <exception cref="ArgumentOutOfRangeException">Port property value is not between <see cref="Transport.PortRangeLow"/> and <see cref="Transport.PortRangeHigh"/>.</exception> protected override void ValidateConfigurationString(string configurationString) { m_configData = configurationString.ParseKeyValuePairs(); // Check for "server" property, this is the preferred configuration for ZeroMQServer if (m_configData.ContainsKey("server")) { // Validate ZeroMQ configuration string Match endpointMatch = Regex.Match(m_configData["server"], EndpointFormatRegex); string port = null; bool validConfigurationString = false; if (endpointMatch.Success) { if (!Enum.TryParse(endpointMatch.Groups["protocol"].Value.Trim(), true, out m_zeroMQTransportProtocol)) { m_zeroMQTransportProtocol = ZeroMQTransportProtocol.Tcp; } m_configData["interface"] = endpointMatch.Groups["host"].Value.Trim(); port = endpointMatch.Groups["port"].Value.Trim(); validConfigurationString = true; } else { // Support traditional IClient "server" property endpointMatch = Regex.Match(m_configData["server"], Transport.EndpointFormatRegex); if (endpointMatch.Success) { m_configData["server"] = $"{m_zeroMQTransportProtocol.ToString().ToLowerInvariant()}://{m_configData["server"]}"; m_configData["interface"] = endpointMatch.Groups["host"].Value.Trim(); port = endpointMatch.Groups["port"].Value.Trim(); validConfigurationString = true; } } if (!validConfigurationString) { throw new FormatException($"Server property is invalid (Example: {DefaultConfigurationString})"); } if (m_zeroMQTransportProtocol != ZeroMQTransportProtocol.InProc && !Transport.IsPortNumberValid(port)) { throw new ArgumentOutOfRangeException(nameof(configurationString), $"Port number must be between {Transport.PortRangeLow} and {Transport.PortRangeHigh}"); } } else { // Fall back on traditional server configuration strings Transport.GetInterfaceIPStack(m_configData); if (string.IsNullOrWhiteSpace(m_configData["interface"]) || m_configData["interface"].Equals("0.0.0.0", StringComparison.Ordinal)) { m_configData["interface"] = "*"; } // For traditional style connection strings, also support a "zeroMQTransportProtocol" setting if (m_configData.ContainsKey("zeroMQTransportProtocol")) { ZeroMQTransportProtocol protocol; if (Enum.TryParse(m_configData["zeroMQTransportProtocol"].Trim(), true, out protocol)) { m_zeroMQTransportProtocol = protocol; } } // For traditional IServer connection strings, a "port" property is expected if (m_configData.ContainsKey("port") && m_zeroMQTransportProtocol != ZeroMQTransportProtocol.InProc) { m_configData["server"] = $"{m_zeroMQTransportProtocol.ToString().ToLowerInvariant()}://{m_configData["interface"]}:{m_configData["port"]}"; } else { throw new FormatException($"Server property is invalid (Example: {DefaultConfigurationString})"); } } }