原文网址: 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();
            }
        }
    }

介绍开源的.net通信框架NetworkComms框架 源码分析(十六 ) ConnectionStatic的更多相关文章

  1. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  2. 深入理解分布式调度框架TBSchedule及源码分析

    简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...

  3. 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...

  4. 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)

    1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e,  要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...

  5. $Django cbv源码分析 djangorestframework框架之APIView源码分析

    1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...

  6. ④NuPlayer播放框架之Renderer源码分析

    [时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...

  7. ⑤NuPlayer播放框架之GenericSource源码分析

    [时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...

  8. ③NuPlayer播放框架之类NuPlayer源码分析

    [时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...

  9. Laravel开发:Laravel框架门面Facade源码分析

    前言 这篇文章我们开始讲 laravel 框架中的门面 Facade,什么是门面呢?官方文档: Facades(读音:/fəˈsäd/ )为应用程序的服务容器中可用的类提供了一个「静态」接口.Lara ...

  10. Android 应用框架层 SQLite 源码分析

    概述   Android 在应用框架层为开发者提供了 SQLite 相关操作接口,其归属于android.database.sqlite包底下,主要包含SQLiteProgram, SQLiteDat ...

随机推荐

  1. Spring-Context之三:使用XML和Groovy DSL配置Bean

    在第一讲中显示了如何使用注解配置bean,其实这是Spring3引进的特性,Spring2使用的是XML的方式来配置Bean,那时候漫天的XML文件使得Spring有着配置地狱的称号.Spring也一 ...

  2. DNS 正向查找与反向查找

    原创地址:http://www.cnblogs.com/jfzhu/p/3996323.html 转载请注明出处 所谓正向查找,就是说在这个区域里的记录可以依据名称来查找对应的IP地址.反向查找就是在 ...

  3. ASP.NET将原始图片按照指定尺寸等比例缩放显示图片

    网站上可能会有很多图片,比如产品图片等,而且他们可能大小不一,宽度和高度也不一定一样,有的很大有的很小.如果放在一张网页上,可能会破坏版面,但是如果强制让他们按照指定的宽度和高度显示,因为比例不同还会 ...

  4. 已经为类型参数“Chart”指定了 constraint 子句。必须在单个 where 子句中指定类型参数的所有约束

    public abstract class FillWorkBook<TModel, Chart> where TModel : struct where Chart : new() wh ...

  5. Atitit。木马病毒原理机密与概论以及防御

    Atitit.木马病毒原理机密与概论以及防御 1. 定时截屏木马1 1.1. QQ聊天与微信聊天木马1 2. 文档木马1 3. 病毒木马的触发方式2 4. 远程木马2 5. 漏洞木马2 6. 病毒木马 ...

  6. rabbitmq消息队列——"工作队列"

    二."工作队列" 在第一节中我们发送接收消息直接从队列中进行.这节中我们会创建一个工作队列来分发处理多个工作者中的耗时性任务. 工作队列主要是为了避免进行一些必须同步等待的资源密集 ...

  7. salesforce 零基础学习(二十八)使用ajax方式实现联动

    之前的一篇介绍过关于salesforce手动配置关联关系实现PickList的联动效果,但是现实的开发中,很多数据不是定死的,应该通过ajax来动态获取,本篇讲述通过JavaScript Remoti ...

  8. 对于System.Net.Http的学习(二)——使用 HttpClient 进行连接

    对于System.Net.Http的学习(一)——System.Net.Http 简介  使用 HttpClient 进行连接 使用 System.Net.Http 命名空间中的 HttpClient ...

  9. webapp启动流程

    webapp启动流程 看了这个教程,其实所有的webapp大致都是这个流程了.

  10. JS原生第二篇 (帅哥)

    1.1 Javascript 作用  1.  网页特效 2. 用户交互 3. 表单验证 Js  就是可以用来控制   结构  和 样式 . 1.2  体验js   认识常用的三个输出语句.  都属于 ...