介绍开源的.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 ...
随机推荐
- C#中使用反射获取结构体实例
一般用反射获取类对象的实例比较简单,只要类有一个无参构造函数或没有显示声明带参的构造函数即可使用如下代码 static void Main(string[] args) { Type type = t ...
- JavaScript-分支语句练习
-1.方程 ax^2+bx+c=0,一元二次方程求根情况. 解: <head><meta http-equiv="Content-Type" content=&q ...
- VM~Linux联不上网
使用桥接的链接方式,centos6.4配置静态ip,能ping通网关,但ping 外网时出现 "network is unreachable" 如:ping www.baidu.c ...
- PHP面向对象06_异常处理
oop06异常处理 2014-9-2 8:36:33 NotePad++ By jiancaigege 摘要: 1.异常处理 2.类中常用函数 异常处理 语法格式: try{ //捕获异常 }catc ...
- atitit..代码生成流程图 流程图绘制解决方案 java c#.net php v2
atitit..代码生成流程图 流程图绘制解决方案 java c#.net php v2 1.1. Markdown 推荐,就是代码和flow都不能直接使用.1 1.2. Java code2fl ...
- iOS-推送通知详解
这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...
- maven install 读取jar包时出错;error in opening zip file
错误信息: [INFO] ------------------------------------------------------------------------ [ERROR] Failed ...
- Python数据类型之“文本序列(Text Sequence)”
Python中的文本序列类型 Python中的文本数据由str对象或字符串进行处理. 1.字符串 字符串是Unicode码值的不可变序列.字符串字面量有多种形式: 单引号:'允许嵌入"双&q ...
- 初了解JS设计模式,学习笔记
什么是设计模式. 回答这个问题,往往我们得先知道我们为什么需要设计模式,正是因为有需求才会有设计模式,难道不是吗? 我们为什么需要设计模式. 如果没有按照设计模式去写,你的代码很可能是乱无肆忌写的,也 ...
- SeaJS与RequireJS最大的区别
SeaJS与RequireJS最大的区别 U_U 2013-06-20 16:21:12 执行模块的机制大不一样-----------------------------------由于 Requir ...