介绍开源的.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 ...
随机推荐
- SVM-非线性支持向量机及SMO算法
SVM-非线性支持向量机及SMO算法 如果您想体验更好的阅读:请戳这里littlefish.top 线性不可分情况 线性可分问题的支持向量机学习方法,对线性不可分训练数据是不适用的,为了满足函数间隔大 ...
- 如何应用Font Awesome矢量字体图标
Font Awesome 是一套专门为 Twitter Boostrap 设计的图标字体库.这套图标字体集几乎囊括了网页中可能用到的所有图标,除了包括 Twitter Boostrap 的默认图标外, ...
- 三天学会HTML5——SVG和Canvas的使用
在第一天学习了HTML5的一些非常重要的基本知识,今天将进行更深层学习 首先来回顾第一天学习的内容,第一天学习了新标签,新控件,验证功能,应用缓存等内容. 第2天将学习如何使用Canvas 和使用SV ...
- [HIMCM暑期班]第3课:一个博弈问题
在一个街道平面图上,住着n个住户.有两个贩卖热狗的商贩,各自想要在街区里摆设一个小摊.每天住户都会去离他家50米范围内的最近的摊点消费.问: 1. 如果两位小贩摆设小摊的顺序有先后(设A先摆,然后B再 ...
- CSS水平垂直居中的几种方法
直接进入主题! 一.脱离文档流元素的居中 方法一:margin:auto法 CSS代码: div{ width: 400px; height: 400px; position: relative; b ...
- Java 9终于要包含Jigsaw项目了
当Jigsaw在Java 9中最终发布时,这个项目的历史已经超过八年了. 转载于:http://www.itxuexiwang.com/a/liunxjishu/2016/0228/180.html? ...
- OutputCache概念学习
目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...
- Searching for a valid kernel header path... The path "" is not a valid path to the ***** kernel headers. Would you like to change it? [yes]
在centos 6.5安装vmtools时候,解压包,mount挂载后,安装pl过程中报 这个问题,半天没有解决,google 后发现这样就行了 I installed the kernel-deve ...
- 经典String str = new String("abc")内存分配问题
出自:http://blog.csdn.net/ycwload/article/details/2650059 今天要找和存储管理相关的一些知识,网上搜了半天也没有找到完善的(30%的程度都不到),没 ...
- 第六节:Vue过滤器的用法和自定义过滤器
1.过滤器的用法,用 '|' 分割表达式和过滤器. 例如:{{ msg | filter}} {{msg | filter(a)}} a就标识filter的一个参数. 用两个过滤器:{{ ...