介绍开源的.net通信框架NetworkComms框架 源码分析(十六 ) ConnectionStatic

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

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

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

Connection NetworkComms.Net中的连接基类    用户交互时使用的类  是TCPConnection和 UDPConnection的基类

   /// <summary>
    /// Global connection base class for NetworkComms.Net. Most user interactions happen using a connection object.
    /// Extended by <see cref="TCPConnection"/> and <see cref="UDPConnection"/>.
    /// NetworkComms.Net中的连接基类    用户交互时使用的类  是TCPConnection和 UDPConnection的基类
    /// </summary>
    #endif
    public abstract partial class Connection
    {
        static ManualResetEvent workedThreadSignal = new ManualResetEvent(false);
        static volatile bool shutdownWorkerThreads = false;
        static object staticConnectionLocker = new object();
#if NETFX_CORE
        static Task connectionKeepAliveWorker;
#else
        static Thread connectionKeepAliveWorker;
#endif

        /// <summary>
        /// Private static constructor which sets the connection defaults
        /// 私有静态构造函数用来设置连接的一个默认参数
        /// </summary>
        static Connection()
        {
            ConnectionKeepAlivePollIntervalSecs = ;
            MaxNumSendTimes = ;
            MinNumSendsBeforeConnectionSpecificSendTimeout = ;
            MinSendTimeoutMS = ;
            MinimumMSPerKBSendTimeout = ;
            DefaultMSPerKBSendTimeout = ;
            NumberOfStDeviationsForWriteTimeout = ;
        }

        /// <summary>
        /// The minimum number of milliseconds to allow per KB before a write timeout may occur. Default is 20.0.
        /// 发送每KB数据所使用的毫秒数  超过将会抛出超时异常 默认20
        /// </summary>
        public static double MinimumMSPerKBSendTimeout { get; set; }

        /// <summary>
        /// The maximum number of writes intervals to maintain. Default is 100.
        /// 写入间隔的最大值 默认100
        /// </summary>
        public static int MaxNumSendTimes { get; set; }

        /// <summary>
        /// The minimum number of writes before the connection specific write timeouts will be used. Default is 4.
        /// 在连接超时前写入的最小数量 默认是4
        /// </summary>
        public static int MinNumSendsBeforeConnectionSpecificSendTimeout { get; set; }

        /// <summary>
        /// The default milliseconds per KB write timeout before connection specific values become available. Default is 1000. See <see cref="MinNumSendsBeforeConnectionSpecificSendTimeout"/>.
        /// 每KB数据发送的超时时间 默认1000毫秒
        /// </summary>
        public static int DefaultMSPerKBSendTimeout { get; set; }

        /// <summary>
        /// The minimum timeout for any sized send in milliseconds. Prevents timeouts when sending less than 1KB. Default is 2000.
        /// 最小发送超时时间    防止发送小于1kb数据时超时
        /// </summary>
        public static int MinSendTimeoutMS { get; set; }

        /// <summary>
        /// The interval between keep alive polls of all connections. Set to int.MaxValue to disable keep alive poll
        /// 发送心跳检测的间隔时间
        /// </summary>
        public static int ConnectionKeepAlivePollIntervalSecs { get; set; }

        /// <summary>
        /// The number of standard deviations from the mean to use for write timeouts. Default is 3.0.
        /// 平均使用写入超时的标准方差  默认3.0
        /// </summary>
        public static double NumberOfStDeviationsForWriteTimeout { get; set; }

        /// <summary>
        /// Starts the connectionKeepAliveWorker thread if it is not already started
        /// 开始心跳检测线程
        /// </summary>
        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
            }
        }

        /// <summary>
        /// A single static worker thread which keeps connections alive
        /// 一个单一的静态工作者线程用来进行心跳检测
        /// </summary>
        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(, false);
                    else
                        workedThreadSignal.WaitOne(, 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();
                    else
                        workedThreadSignal.WaitOne();
#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");
                }
            }
        }

        /// <summary>
        /// Polls all existing connections based on ConnectionKeepAlivePollIntervalSecs value. Server side connections are polled
        /// slightly earlier than client side to help reduce potential congestion.
        /// 给所有连接发送空数据包进行心跳检测 服务器端发送心跳检测的时间小于客户端
        /// </summary>
        /// <param name="returnImmediately">If true runs as task and returns immediately.</param>
        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);
            ; i < allConnections.Count; i++)
            {
                //We don't send null packets to unconnected UDP connections
                //UDP连接上我们不发送空数据包
                UDPConnection asUDP = allConnections[i] as UDPConnection;
                if (asUDP != null && asUDP.ConnectionUDPOptions == UDPOptions.None)
                {
                    )
                        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
                        {
                            )
                                allConnectionsComplete.Set();
                        }
                    }), null);
                }
            }

            //Max wait is 1 seconds per connection
            //每个连接最多等待1秒
            )
            {
#if NET2
                , false))
#else
                ))
#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.");
            }
        }

        /// <summary>
        /// Shutdown any static connection components
        /// 关闭静态连接组件
        /// </summary>
        /// <param name="threadShutdownTimeoutMS"></param>
        )
        {
            try
            {
                StopListening();
            }
            catch (Exception ex)
            {
                LogTools.LogException(ex, "CommsShutdownError");
            }

            try
            {
                shutdownWorkerThreads = true;
#if NETFX_CORE
                if (connectionKeepAliveWorker != null && !connectionKeepAliveWorker.Wait(threadShutdownTimeoutMS))
                    throw new CommsSetupShutdownException("Connection keep alive worker failed to shutdown");
#else
                if (connectionKeepAliveWorker != null && !connectionKeepAliveWorker.Join(threadShutdownTimeoutMS))
                    connectionKeepAliveWorker.Abort();
#endif
            }
            catch (Exception ex)
            {
                LogTools.LogException(ex, "CommsShutdownError");
            }
            finally
            {
                shutdownWorkerThreads = false;
                workedThreadSignal.Reset();
            }
        }
    }
上一篇:Linux C编程--main函数参数解析


下一篇:shell知识点小结