/// <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());
        }
Exemple #2
0
        /// <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());
        }