/// <summary> /// Terminates the server as quickly as possible and /// removes it from the collection of shared servers. /// </summary> // ReSharper disable once UnusedMember.Local private void TerminateSharedClient() { EndPoint localEndPoint; TcpServer sharedServer; lock (s_sharedServers) { localEndPoint = GetLocalEndPoint(); if (s_sharedServers.TryGetValue(localEndPoint, out sharedServer)) { // If the wrapped server and the shared server are the same, // no one has terminated the shared server yet if (m_tcpServer == sharedServer) { // Disconnect and dispose of the old server m_tcpServer.Stop(); m_tcpServer.Dispose(); // Remove the old server from the // collection of shared servers localEndPoint = GetLocalEndPoint(); s_sharedServers.Remove(localEndPoint); s_sharedReferenceCount.Remove(localEndPoint); } } m_tcpServer = null; } }
/// <summary> /// Gets a reference to the shared server listening /// on this server's local end point. /// </summary> /// <returns>A reference to a shared server.</returns> private void GetSharedServer() { const string ConfigurationMismatchError = "Configuration mismatch detected between parsers using shared TCP server: {0}"; bool sharing; EndPoint localEndPoint; TcpServer sharedServer; lock (s_sharedServers) { localEndPoint = GetLocalEndPoint(); sharing = s_sharedServers.TryGetValue(localEndPoint, out sharedServer); if (sharing) { // Validate settings to ensure that they match if (sharedServer.ReceiveBufferSize != m_receiveBufferSize) throw new InvalidOperationException(string.Format(ConfigurationMismatchError, "Receive buffer size")); } else { // Create new client and add it to the shared list sharedServer = new TcpServer(); s_sharedServers.Add(localEndPoint, sharedServer); s_sharedReferenceCount.Add(localEndPoint, 0); } // Set the TCP server member variable ASAP to guarantee // that it is set before callbacks can be triggered m_tcpServer = sharedServer; // Attach to event handlers sharedServer.ClientConnected += SharedServer_ClientConnected; sharedServer.ClientDisconnected += SharedServer_ClientDisconnected; sharedServer.ClientConnectingException += SharedServer_ClientConnectingException; sharedServer.ReceiveClientData += SharedServer_ReceiveClientData; sharedServer.ReceiveClientDataException += SharedServer_ReceiveClientDataException; sharedServer.SendClientDataException += SharedServer_SendClientDataException; sharedServer.ServerStarted += SharedServer_ServerStarted; sharedServer.ServerStopped += SharedServer_ServerStopped; sharedServer.UnhandledUserException += SharedServer_UnhandledUserException; if (!sharing) { // Initialize settings and connect sharedServer.ConfigurationString = m_configurationString; sharedServer.ReceiveBufferSize = m_receiveBufferSize; sharedServer.Start(); } // Increment reference count s_sharedReferenceCount[localEndPoint]++; } }
/// <summary> /// Releases a reference to this server's shared server, /// and disposes of the shared server if nobody is using it. /// </summary> private void ReturnSharedServer() { EndPoint localEndPoint; lock (s_sharedServers) { if ((object)m_tcpServer == null) return; // Detach from event handlers m_tcpServer.ClientConnected -= SharedServer_ClientConnected; m_tcpServer.ClientDisconnected -= SharedServer_ClientDisconnected; m_tcpServer.ReceiveClientData -= SharedServer_ReceiveClientData; m_tcpServer.ReceiveClientDataException -= SharedServer_ReceiveClientDataException; m_tcpServer.SendClientDataException -= SharedServer_SendClientDataException; m_tcpServer.ServerStarted -= SharedServer_ServerStarted; m_tcpServer.ServerStopped -= SharedServer_ServerStopped; m_tcpServer.UnhandledUserException -= SharedServer_UnhandledUserException; // Decrement reference count localEndPoint = GetLocalEndPoint(); s_sharedReferenceCount[localEndPoint]--; if (s_sharedReferenceCount[localEndPoint] == 0) { // No more references to TCP server // exist so dispose of it m_tcpServer.Stop(); m_tcpServer.Dispose(); s_sharedServers.Remove(localEndPoint); s_sharedReferenceCount.Remove(localEndPoint); } // Release reference to TCP server m_tcpServer = null; } }
/// <summary> /// Initializes a new instance of the <see cref="DataListener"/> class. /// </summary> public DataListener() { m_id = DefaultID; m_server = DefaultServer; m_port = DefaultPort; m_protocol = DefaultProtocol; m_connectToServer = DefaultConnectToServer; m_cacheData = DefaultCacheData; m_initializeData = DefaultInitializeData; m_initializeDataTimeout = DefaultInitializeDataTimeout; m_persistSettings = DefaultPersistSettings; m_settingsCategory = DefaultSettingsCategory; m_data = new List<IDataPoint>(); m_clientIDs = new ConcurrentDictionary<IClient, Guid>(); m_initializeWaitHandle = new AutoResetEvent(false); m_parser = new PacketParser(); m_parser.DataParsed += PacketParser_DataParsed; m_tcpClient = new TcpClient(); m_tcpClient.ConnectionAttempt += ClientSocket_ConnectionAttempt; m_tcpClient.ConnectionEstablished += ClientSocket_ConnectionEstablished; m_tcpClient.ConnectionTerminated += ClientSocket_ConnectionTerminated; m_tcpClient.ReceiveDataComplete += ClientSocket_ReceiveDataComplete; m_clientIDs.TryAdd(m_tcpClient, Guid.NewGuid()); m_udpClient = new UdpClient(); m_udpClient.ConnectionAttempt += ClientSocket_ConnectionAttempt; m_udpClient.ConnectionEstablished += ClientSocket_ConnectionEstablished; m_udpClient.ConnectionTerminated += ClientSocket_ConnectionTerminated; m_udpClient.ReceiveDataComplete += ClientSocket_ReceiveDataComplete; m_clientIDs.TryAdd(m_udpClient, Guid.NewGuid()); m_tcpServer = new TcpServer(); m_tcpServer.ServerStarted += ServerSocket_ServerStarted; m_tcpServer.ServerStopped += ServerSocket_ServerStopped; m_tcpServer.ReceiveClientDataComplete += ServerSocket_ReceiveClientDataComplete; m_dataInitClient = new TcpClient(); m_dataInitClient.ConnectionString = "Server={0}:1003; interface=0.0.0.0"; m_dataInitClient.PayloadAware = true; m_dataInitClient.MaxConnectionAttempts = 10; m_dataInitClient.ReceiveDataComplete += DataInitClient_ReceiveDataComplete; }
private TcpServer InitializeTcpServer() { TcpServer remotingServer; remotingServer = new TcpServer(); remotingServer.ConfigurationString = "Port=8500"; remotingServer.IgnoreInvalidCredentials = true; remotingServer.PayloadAware = true; remotingServer.PersistSettings = true; remotingServer.SettingsCategory = "RemotingServer"; remotingServer.Initialize(); return remotingServer; }
/// <summary> /// Create a communications server /// </summary> /// <remarks> /// Note that typical configuration string should be prefixed with a "protocol=tcp" or a "protocol=udp" /// </remarks> /// <param name="configurationString">The configuration string for the server.</param> /// <returns>A communications server.</returns> public static IServer Create(string configurationString) { Dictionary<string, string> configurationSettings = configurationString.ParseKeyValuePairs(); IServer server; string protocol; if (configurationSettings.TryGetValue("protocol", out protocol)) { configurationSettings.Remove("protocol"); StringBuilder settings = new StringBuilder(); foreach (string key in configurationSettings.Keys) { settings.Append(key); settings.Append("="); settings.Append(configurationSettings[key]); settings.Append(";"); } // Create a server instance for the specified protocol. switch (protocol.Trim().ToLower()) { case "tls": server = new TlsServer(settings.ToString()); break; case "tcp": server = new TcpServer(settings.ToString()); break; case "udp": server = new UdpServer(settings.ToString()); break; case "zeromq": server = new ZeroMQServer(settings.ToString()); break; default: throw new ArgumentException("Transport protocol \'" + protocol + "\' is not valid"); } // Apply server settings from the connection string to the client. foreach (KeyValuePair<string, string> setting in configurationSettings) { PropertyInfo property = server.GetType().GetProperty(setting.Key); if (property != null) property.SetValue(server, Convert.ChangeType(setting.Value, property.PropertyType), null); } } else { throw new ArgumentException("Transport protocol must be specified"); } return server; }
/// <summary> /// Creates a new <see cref="ClientConnection"/> instance. /// </summary> /// <param name="parent">Parent data publisher.</param> /// <param name="clientID">Client ID of associated connection.</param> /// <param name="commandChannel"><see cref="TcpServer"/> command channel used to lookup connection information.</param> public ClientConnection(DataPublisher parent, Guid clientID, TcpServer commandChannel) { m_parent = parent; m_clientID = clientID; m_commandChannel = commandChannel; m_subscriberID = clientID; m_keyIVs = null; m_cipherIndex = 0; // Setup ping timer m_pingTimer = new System.Timers.Timer(); m_pingTimer.Interval = 5000.0D; m_pingTimer.AutoReset = true; m_pingTimer.Elapsed += m_pingTimer_Elapsed; m_pingTimer.Start(); // Setup reconnect timer m_reconnectTimer = new System.Timers.Timer(); m_reconnectTimer.Interval = 1000.0D; m_reconnectTimer.AutoReset = false; m_reconnectTimer.Elapsed += m_reconnectTimer_Elapsed; // Attempt to lookup remote connection identification for logging purposes try { TransportProvider<Socket> client; IPEndPoint remoteEndPoint = null; if ((object)commandChannel != null && commandChannel.TryGetClient(clientID, out client)) remoteEndPoint = client.Provider.RemoteEndPoint as IPEndPoint; if ((object)remoteEndPoint != null) { m_ipAddress = remoteEndPoint.Address; if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6) m_connectionID = "[" + m_ipAddress + "]:" + remoteEndPoint.Port; else m_connectionID = m_ipAddress + ":" + remoteEndPoint.Port; try { IPHostEntry ipHost = Dns.GetHostEntry(remoteEndPoint.Address); if (!ipHost.HostName.IsNullOrWhiteSpace()) { m_hostName = ipHost.HostName; m_connectionID = m_hostName + " (" + m_connectionID + ")"; } } catch { // Just ignoring possible DNS lookup failures... } } } catch { // At worst we'll just use the client GUID for identification m_connectionID = (m_subscriberID == Guid.Empty ? clientID.ToString() : m_subscriberID.ToString()); } if (m_connectionID.IsNullOrWhiteSpace()) m_connectionID = "unavailable"; if (m_hostName.IsNullOrWhiteSpace()) { if (m_ipAddress != null) m_hostName = m_ipAddress.ToString(); else m_hostName = m_connectionID; } if (m_ipAddress == null) m_ipAddress = System.Net.IPAddress.None; }
/// <summary> /// Releases the unmanaged resources used by the <see cref="ClientConnection"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if (m_pingTimer != null) { m_pingTimer.Elapsed -= m_pingTimer_Elapsed; m_pingTimer.Dispose(); } m_pingTimer = null; if (m_reconnectTimer != null) { m_reconnectTimer.Elapsed -= m_reconnectTimer_Elapsed; m_reconnectTimer.Dispose(); } m_reconnectTimer = null; DataChannel = null; m_commandChannel = null; m_ipAddress = null; m_subscription = null; m_parent = null; } } finally { m_disposed = true; // Prevent duplicate dispose. } } }