你的位置:首页 > ASP.net教程

[ASP.net教程]介绍开源的.net通信框架NetworkComms框架之五 心跳检测


原文网址: http://www.cnblogs.com/csdev

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是:Apache License v2

开源地址是:https://github.com/MarcFletcher/NetworkComms.Net

我们知道TCP连接建立之后,如果没有心跳检测,连接一会就断开了。NetworkComms框架本身已经完美实现了心跳检测,我们在使用的时候不用再关心这个问题。

NetworkComms通信框架中服务器端设定的发送心跳消息的时间小于客户端发送心跳消息,所以发送心跳消息的工作主要由服务器端来完成。

如果服务器端超出常规时间没有发送心跳消息,客户端才会开始发送。

相关实现代码:

ConnectionStatic方法中:

 protected static void TriggerConnectionKeepAliveThread()    {      lock (staticConnectionLocker)      {#if NETFX_CORE        if (!shutdownWorkerThreads && (connectionKeepAliveWorker == null || connectionKeepAliveWorker.IsCompleted))        {          connectionKeepAliveWorker = new Task(ConnectionKeepAliveWorker, TaskCreationOptions.LongRunning);          connectionKeepAliveWorker.Start();        }#else        if (!shutdownWorkerThreads && (connectionKeepAliveWorker == null || connectionKeepAliveWorker.ThreadState == ThreadState.Stopped))        {          connectionKeepAliveWorker = new Thread(ConnectionKeepAliveWorker);          connectionKeepAliveWorker.Name = "ConnectionKeepAliveWorker";          connectionKeepAliveWorker.IsBackground = true;          connectionKeepAliveWorker.Start();        }#endif      }    }

 private static void ConnectionKeepAliveWorker()    {      if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Connection keep alive polling thread has started.");      DateTime lastPollCheck = DateTime.Now;      while (!shutdownWorkerThreads)      {        try        {#if NET2          //We have a short sleep here so that we can exit the thread fairly quickly if we need too          if (ConnectionKeepAlivePollIntervalSecs == int.MaxValue)            workedThreadSignal.WaitOne(5000, false);          else            workedThreadSignal.WaitOne(100, false);#else          //We have a short sleep here so that we can exit the thread fairly quickly if we need too          if (ConnectionKeepAlivePollIntervalSecs == int.MaxValue)            workedThreadSignal.WaitOne(5000);          else            workedThreadSignal.WaitOne(100);#endif          //Check for shutdown here          if (shutdownWorkerThreads) break;          //Any connections which we have not seen in the last poll interval get tested using a null packet          if (ConnectionKeepAlivePollIntervalSecs < int.MaxValue && (DateTime.Now - lastPollCheck).TotalSeconds > (double)ConnectionKeepAlivePollIntervalSecs)          {            AllConnectionsSendNullPacketKeepAlive();            lastPollCheck = DateTime.Now;          }        }        catch (Exception ex)        {          LogTools.LogException(ex, "ConnectionKeepAlivePollError");        }      }    }

 private static void AllConnectionsSendNullPacketKeepAlive(bool returnImmediately = false)    {      if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Starting AllConnectionsSendNullPacketKeepAlive");      //Loop through all connections and test the alive state      List<Connection> allConnections = NetworkComms.GetExistingConnection(ApplicationLayerProtocolStatus.Enabled);      int remainingConnectionCount = allConnections.Count;      QueueItemPriority nullSendPriority = QueueItemPriority.AboveNormal;            ManualResetEvent allConnectionsComplete = new ManualResetEvent(false);      for (int i = 0; i < allConnections.Count; i++)      {        //We don't send null packets to unconnected UDP connections        UDPConnection asUDP = allConnections[i] as UDPConnection;        if (asUDP != null && asUDP.ConnectionUDPOptions == UDPOptions.None)        {          if (Interlocked.Decrement(ref remainingConnectionCount) == 0)            allConnectionsComplete.Set();          continue;        }        else        {          int innerIndex = i;          NetworkComms.CommsThreadPool.EnqueueItem(nullSendPriority, new WaitCallback((obj) =>          {            try            {              //If the connection is server side we poll preferentially              if (allConnections[innerIndex] != null)              {                if (allConnections[innerIndex].ConnectionInfo.ServerSide)                {                  //We check the last incoming traffic time                  //In scenarios where the client is sending us lots of data there is no need to poll                  if ((DateTime.Now - allConnections[innerIndex].ConnectionInfo.LastTrafficTime).TotalSeconds > ConnectionKeepAlivePollIntervalSecs)                    allConnections[innerIndex].SendNullPacket();                }                else                {                  //If we are client side we wait up to an additional 3 seconds to do the poll                  //This means the server will probably beat us                  if ((DateTime.Now - allConnections[innerIndex].ConnectionInfo.LastTrafficTime).TotalSeconds > ConnectionKeepAlivePollIntervalSecs + 1.0 + (NetworkComms.randomGen.NextDouble() * 2.0))                    allConnections[innerIndex].SendNullPacket();                }              }            }            catch (Exception) { }            finally            {              if (Interlocked.Decrement(ref remainingConnectionCount) == 0)                allConnectionsComplete.Set();            }          }), null);        }      }      //Max wait is 1 seconds per connection      if (!returnImmediately && allConnections.Count > 0)      {#if NET2        if (!allConnectionsComplete.WaitOne(allConnections.Count * 2500, false))#else        if (!allConnectionsComplete.WaitOne(allConnections.Count * 2500))#endif          //This timeout should not really happen so we are going to log an error if it does          //LogTools.LogException(new TimeoutException("Timeout after " + allConnections.Count.ToString() + " seconds waiting for null packet sends to finish. " + remainingConnectionCount.ToString() + " connection waits remain. This error indicates very high send load or a possible send deadlock."), "NullPacketKeepAliveTimeoutError");          if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Warn("Timeout after " + allConnections.Count.ToString() + " seconds waiting for null packet sends to finish. " + remainingConnectionCount.ToString() + " connection waits remain. This error indicates very high send load or a possible send deadlock.");      }    }

 

原文网址: http://www.cnblogs.com/csdev