/// <summary> /// Close disconnected client sockets, send heartbeat messages and do other assorted cleanup. /// </summary> private void MaintenanceThread() { //Prepare the heartbeat message TCPHeartbeatMessage heartbeat = new TCPHeartbeatMessage(); BinaryFormatter bf = new BinaryFormatter(); MemoryStream hbms = new MemoryStream(); bf.Serialize(hbms, heartbeat); byte[] hbbuf = hbms.GetBuffer(); int hblen = (int)hbms.Length; MessageTags hbtags = new MessageTags(); //Lists for socket maintenance List<Guid> toCleanup = new List<Guid>(); List<Socket> toClose = new List<Socket>(); int secondCounter = 0; int connectedClientCount = 0; while (!this.m_Disposed) { //iterate approximately once per second for (int i = 0; ((i < 10) && (!m_Disposed)); i++) { Thread.Sleep(100); } if (this.m_Disposed) break; secondCounter++; lock (m_AllClients) { //Close and remove disconnected sockets. toCleanup.Clear(); toClose.Clear(); connectedClientCount = 0; foreach (ClientData client in m_AllClients.Values) { if (client.ConnectionState == ConnectionState.Disconnected) { //Check for disconnected clients that have timed out if (client.Timeout < DateTime.Now) { this.m_ServerSender.RemoveQueue(client.Id); toCleanup.Add(client.Id); } } else if (client.ConnectionState == ConnectionState.Connected) { //Find sockets to close for any new disconnects if (!client.Socket.Connected) { toClose.Add(client.Socket); client.Socket = null; client.ConnectionState = ConnectionState.Disconnected; client.Timeout = DateTime.Now + TimeSpan.FromMinutes(m_QueueTimeout); } else { connectedClientCount++; //Send a heartbeat message to connected clients if (secondCounter % HEARTBEAT_PERIOD == 0) { //Trace.WriteLine("TCPServer sending Heartbeat to client ID " + client.Id.ToString(), this.GetType().ToString()); this.m_ServerSender.Send(hbbuf, hblen, client, hbtags,0,0,true); } } } else if (client.ConnectionState == ConnectionState.Reconnecting) { //This is a temporary state used during handshaking connectedClientCount++; } } //Remove timed out clients from the master list foreach (Guid goner in toCleanup) { m_AllClients.Remove(goner); } } //Update published client count if (m_ClientCount != connectedClientCount) { using (Synchronizer.Lock(this.SyncRoot)) { this.SetPublishedProperty("ClientCount", ref m_ClientCount, connectedClientCount); NetworkStatus newStatus = m_NetworkStatus.Clone(); newStatus.ClientCount = m_ClientCount; this.SetPublishedProperty("NetworkStatus", ref m_NetworkStatus, newStatus); } } //Close sockets foreach (Socket s in toClose) { try { Trace.WriteLine("MaintenanceThread closing disconnected socket: " + s.RemoteEndPoint.ToString(), this.GetType().ToString()); s.Close(); } catch (Exception e) { Trace.WriteLine("MaintenanceThread exception while closing socket: " + e.ToString(), this.GetType().ToString()); } } if (toCleanup.Count > 0) Trace.WriteLine("MaintenanceThread timed out " + toCleanup.Count.ToString() + " disconnected socket(s).", this.GetType().ToString()); //Print a heartbeat to the log just to make it easier to parse by eye. if (secondCounter%10 == 0) { Trace.WriteLine(DateTime.Now.ToString(), this.GetType().ToString()); } } Trace.WriteLine("MaintenanceThread is ending.", this.GetType().ToString()); }
/// <summary> /// Close disconnected client sockets, send heartbeat messages and do other assorted cleanup. /// </summary> private void MaintenanceThread() { //Prepare the heartbeat message TCPHeartbeatMessage heartbeat = new TCPHeartbeatMessage(); BinaryFormatter bf = new BinaryFormatter(); MemoryStream hbms = new MemoryStream(); #if GENERIC_SERIALIZATION heartbeat.Serialize().WriteToStream(hbms); #else bf.Serialize(hbms, heartbeat); #endif byte[] hbbuf = hbms.GetBuffer(); int hblen = (int)hbms.Length; MessageTags hbtags = new MessageTags(); //Lists for socket maintenance List <Guid> toCleanup = new List <Guid>(); List <Socket> toClose = new List <Socket>(); int secondCounter = 0; int connectedClientCount = 0; while (!this.m_Disposed) { //iterate approximately once per second for (int i = 0; ((i < 10) && (!m_Disposed)); i++) { Thread.Sleep(100); } if (this.m_Disposed) { break; } secondCounter++; lock (m_AllClients) { //Close and remove disconnected sockets. toCleanup.Clear(); toClose.Clear(); connectedClientCount = 0; foreach (ClientData client in m_AllClients.Values) { if (client.ConnectionState == ConnectionState.Disconnected) { //Check for disconnected clients that have timed out if (client.Timeout < DateTime.Now) { this.m_ServerSender.RemoveQueue(client.Id); toCleanup.Add(client.Id); } } else if (client.ConnectionState == ConnectionState.Connected) { //Find sockets to close for any new disconnects if (!client.Socket.Connected) { toClose.Add(client.Socket); client.Socket = null; client.ConnectionState = ConnectionState.Disconnected; client.Timeout = DateTime.Now + TimeSpan.FromMinutes(m_QueueTimeout); } else { connectedClientCount++; //Send a heartbeat message to connected clients if (secondCounter % HEARTBEAT_PERIOD == 0) { //Trace.WriteLine("TCPServer sending Heartbeat to client ID " + client.Id.ToString(), this.GetType().ToString()); this.m_ServerSender.Send(hbbuf, hblen, client, hbtags, 0, 0, true); } } } else if (client.ConnectionState == ConnectionState.Reconnecting) { //This is a temporary state used during handshaking connectedClientCount++; } } //Remove timed out clients from the master list foreach (Guid goner in toCleanup) { m_AllClients.Remove(goner); } } //Update published client count if (m_ClientCount != connectedClientCount) { using (Synchronizer.Lock(this.SyncRoot)) { this.SetPublishedProperty("ClientCount", ref m_ClientCount, connectedClientCount); NetworkStatus newStatus = m_NetworkStatus.Clone(); newStatus.ClientCount = m_ClientCount; this.SetPublishedProperty("NetworkStatus", ref m_NetworkStatus, newStatus); } } //Close sockets foreach (Socket s in toClose) { try { Trace.WriteLine("MaintenanceThread closing disconnected socket: " + s.RemoteEndPoint.ToString(), this.GetType().ToString()); s.Close(); } catch (Exception e) { Trace.WriteLine("MaintenanceThread exception while closing socket: " + e.ToString(), this.GetType().ToString()); } } if (toCleanup.Count > 0) { Trace.WriteLine("MaintenanceThread timed out " + toCleanup.Count.ToString() + " disconnected socket(s).", this.GetType().ToString()); } //Print a heartbeat to the log just to make it easier to parse by eye. if (secondCounter % 10 == 0) { Trace.WriteLine(DateTime.Now.ToString(), this.GetType().ToString()); } } Trace.WriteLine("MaintenanceThread is ending.", this.GetType().ToString()); }