介绍开源的.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(); } } }
介绍开源的.net通信框架NetworkComms框架 源码分析(十六 ) ConnectionStatic的更多相关文章
- DotNetty网络通信框架学习之源码分析
DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...
- 深入理解分布式调度框架TBSchedule及源码分析
简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...
- 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)
1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...
- 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)
1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...
- $Django cbv源码分析 djangorestframework框架之APIView源码分析
1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...
- ④NuPlayer播放框架之Renderer源码分析
[时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...
- ⑤NuPlayer播放框架之GenericSource源码分析
[时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...
- ③NuPlayer播放框架之类NuPlayer源码分析
[时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...
- Laravel开发:Laravel框架门面Facade源码分析
前言 这篇文章我们开始讲 laravel 框架中的门面 Facade,什么是门面呢?官方文档: Facades(读音:/fəˈsäd/ )为应用程序的服务容器中可用的类提供了一个「静态」接口.Lara ...
- Android 应用框架层 SQLite 源码分析
概述 Android 在应用框架层为开发者提供了 SQLite 相关操作接口,其归属于android.database.sqlite包底下,主要包含SQLiteProgram, SQLiteDat ...
随机推荐
- Chrome扩展程序的二次开发:把它改得更适合自己使用
我当然知道未经作者允许修改别人程序是不道德的了,但作为学习研究之用还是无可厚非,这里仅供交流. 一切都是需求驱动的 话说某天我在网上猎奇的时候无意间发现这么一款神奇的谷歌浏览器插件:Extension ...
- iOS xcode6 设置多语言
1,首先新建一个文件,选中ios模块下Rescource的Strings File 类型.eg:文件 2,选中该文件,右边栏选该文件属性,选中Localizable模块,选中localiz,这时会弹出 ...
- OutputCache属性详解(四)— SqlDependency
目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...
- 学习ASP.NET MVC(五)——我的第一个ASP.NET MVC CURD页面
在上一篇文章中我们已经创建了实体类,在这一篇文章中,我将创建一个新的控制器类——BookController,使用BookController对Books表中的数据进行CURD操作的方法,并使用视图模 ...
- Archlinux 2015.07.01 和 Windows7 双系统 安装教程
提前在windows7下给Archlinux预留一个分区,大小最好在20G以上(根据自己硬盘情况分配). 第一步,安装前的准备 从arch官网下载最新的ISO文件archlinux-2015.07.0 ...
- ECMAScript 位运算符
位运算符是在数字底层(即表示数字的 32 个数位)进行操作的. 重温整数 ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数).在 ECMAScript ...
- WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享
系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...
- Android中常用控件及属性
在之前的博客为大家带来了很多关于Android和jsp的介绍,本篇将为大家带来,关于Andriod中常用控件及属性的使用方法,目的方便大家遗忘时,及时复习参考.好了废话不多讲,现在开始我们本篇内容的介 ...
- java中线程存活和线程执行的问题!
/* 下面的程序会出现下面的情况,当Thread-0, Thread-1, Thread-2都被wait的时候,可能会同时苏醒 Thread-0 put Thread-1 put Thread-2 p ...
- Docker之Linux Cgroups
Linux Cgroups介绍 上面是构建Linux容器的namespace技术,它帮进程隔离出自己单独的空间,但Docker又是怎么限制每个空间的大小,保证他们不会互相争抢呢?那么就要用到Linux ...