几天前在博问中看到一个C# Socket问题就想到笔者年做的一个省级交通流量接收服务器项目当时的基本求如下
接收自动观测设备通过无线网卡Internet和Socket上报的交通量数据包 全年*运行的自动观测设备分钟上报一次观测数据每笔记录约K大小 规划全省将有个左右的自动观测设备(截止年月还只有个)
当时VS才发布年多笔者也是接触C#不久于是Google了国内国外网希望找点应用C#解决Socket通信问题的思路和代码最后找到了两篇帮助最大的文章一篇是国人写的Socket接收器框架应用了独立的客户端Socket会话(Session)概念给笔者提供了一个接收服务器的总体框架思路另一篇是美国人写的提出了多线程分段接收数据包的技术方案描述了多线程异步Socket的许多实现细节该文坚定了笔者采用多线程和异步方式处理Socket接收器的技术路线
具体实现和测试时笔者还发现在Internet环境下的Socket应用中需要系统有极强的容错能力没有办法控制异常就必须允许它们存在(附加源代码中可以看到try{}catch{}语句较多)对此笔者设计了一个专门的检查和清理线程完成无效或超时会话的清除和资源释放工作
依稀记得国内框架作者的名称空间有ibm认为是IBM公司职员通过邮件后才知道其人在深圳笔者向他请教了几个问题相互探讨了几个技术关键点可惜现在再去找已经查不到原文和邮件了只好借此机会将本文献给这两个素未谋面的技术高人和同行也盼望拙文或源码能给读者一点有用的启发和帮助
主要技术思路
整个系统由三个核心线程组成并由NET线程池统一管理
侦听客户端连接请求线程ListenClientRequest()循环侦听客户端连接请求如果有检测该客户端IP看是否是同一观测设备然后建立一个客户端TSession对象并通过Socket异步调用方法BeginReceive()接收数据包EndReceive()处理数据包 数据包处理线程HandleDatagrams()循环检测数据包队列_datagramQueue完成数据包解析判断类型存储等工作 客户端状态检测线程CheckClientState()循环检查客户端会话表_sessionTable判断会话对象是否有效设置超时会话关闭标志清楚无效会话对象及释放其资源 主要类简介
系统主要由个类组成
TDatagramReceiver(数据包接收服务器)系统的核心进程类建立Socket连接处理与存储数据包清理系统资源该类提供全部的public属性和方法 TSession(客户端会话)由每个客户端的Socket对象组成有自己的数据缓沖区清理线程根据该对象的最近会话时间判断是否超时 TDatagram(数据包类)判断数据包类别解析数据包
关键函数和代码
下面简介核心类TDatagramReceiver的关键实现代码
系统启动
系统启动方法StartReceiver()首先清理资源创建数据库连接初始化若干计数值
然后创建服务器端侦听Socket对象最后调用静态方法ThreadPoolQueueUserWorkItem()在线程池中创建个核心处理线程
Code
///
/// 启动接收器
///
public bool StartReceiver()
{
try
{
_stopReceiver = true;
thisClose();
if (!thisConnectDatabase()) return false;
_clientCount = ;
_datagramQueueCount = ;
_datagramCount = ;
_errorDatagramCount = ;
_exceptionCount = ;
_sessionTable = new Hashtable(_maxAllowClientCount);
_datagramQueue = new Queue<TDatagram>(_maxAllowDate)