此协议接收器可以最大可以接收不超过10MB的单条协议。 此协议接收器单个实例可以稳定的接收到168KB/S的协议数据。累计运行时间超过20000小时
实例化后 主要调用方法
ReceiveActive
收到一打完整的协议后将引发
OnProtocolReceived 事件
协议的反序列化,为CLR对像在
protected virtual void ProtocolReceivedByThreadPool(byte[] byteProtocolData)
方法中进行
方法需要实例化
/// <summary>
/// Dect 协议接收 解析 器
/// </summary>
public class DectProtocolReceiver
{
#region 子类可见的属性
#endregion
#region 构造函数
/// <summary>
/// 创建一个新的协议解析器对像
/// </summary>
public DectProtocolReceiver()
{
}
#endregion
#region 子类可见的方法
/// <summary>
/// 在data的byte数组搜索pattern出现的位置
/// C#实现byte[]搜索
/// 还是比较简单的功能,在data的byte数组搜索pattern出现的位置。当然这里可以对该功能进行扩展,例如实现忽略大小写,并防止异常情况等等。
/// </summary>
/// <param name="data">data的byte数组搜索</param>
/// <param name="pattern">搜索pattern出现的位置</param>
/// <returns>返回的结果是一个List int ,如果其大小为0,则说明搜索失败。</returns>
protected virtual List<int> indexOf(byte[] data, byte[] pattern)
{
///List int 临时变量
List<int> matchedPos = new List<int>();
///看看当前数据可不可以进行搜索
if (data.Length == 0 || data.Length < pattern.Length)
{
return matchedPos;
}
//计算搜索结束的长度
int end = data.Length - pattern.Length;
//是不是搜索到了
bool matched = false;
//开始进行搜索
for (int i = 0; i <= end; i++)
{
//单字节搜索
for (int j = 0; j < pattern.Length || !(matched = (j == pattern.Length)); j++)
{
if (data[i + j] != pattern[j]) break;
}
if (matched)
{
matched = false;
matchedPos.Add(i);
}
}
return matchedPos;
}
#if SILVERLIGHT
GB2312.GB2312Encoding gb2312 = new GB2312.GB2312Encoding();
#endif
/// <summary>
/// 用于线程池里 接收到的方法
/// 处理协议数据 包括反序列化等功能
/// 事件通知已经接收到协议
/// </summary>
/// <param name="byteProtocolData">协议数据Buffer</param>
protected virtual void ProtocolReceivedByThreadPool(byte[] byteProtocolData)
{
//临时字符串
string mathe = ASCIIEncoding.ASCII.GetString(byteProtocolData, 0, byteProtocolData.Length);
/*
这里是解协议的序列化方法
*/
RegistOnProtocolReceived(mathe);
}
#endregion
#region 变量定义
/// <summary>
/// 字节缓存
/// 使用 fOREACH 性能测试 5242880 次添加 耗时 78.123 毫秒
/// </summary>
private Queue<byte> byteCache = new Queue<byte>();
/// <summary>
/// 拆分协议用的字符串或者byte[]
/// </summary>
private byte[] SplicSpace = ASCIIEncoding.ASCII.GetBytes("\r\n");
/// <summary>
/// 定义一个 线程池回调函数
/// </summary>
private System.Threading.WaitCallback ThreadPoolFun = null;
#endregion
#region IProtocolReceiver 成员
/// <summary>
/// 接收数据动作
/// </summary>
/// <param name="byteArray">收到的数据</param>
public virtual void ReceiveActive(byte[] byteArray)
{
#region 解压
ReceiveActiveDCompress(byteArray);
#endregion
}
/// <summary>
/// 接收数据 带解压缩 动作
/// </summary>
/// <param name="byteArray">收到的数据</param>
public virtual void ReceiveActiveDCompress(byte[] byteArray)
{
if (byteArray.Length > 0)
{
//如果大于10M数据清空
//此处用于对服务器发送大量错误数据后处理
if (byteCache.Count > 1024 * 1024 * 10)
{
//清空数据保证内存不上涨
byteCache.Clear();
}
//如果不是初始化的数据
if (byteArray.Length != 1 && byteArray != new byte[1])
{
#region 添加到缓存队列
/// 将对象添加到 System.Collections.Generic.Queue<T> 的结尾处。
foreach (byte b in byteArray)
{
// 将对象添加到 System.Collections.Generic.Queue<T> 的结尾处。
byteCache.Enqueue(b);
}
#endregion
//搜索 分割符 出现的位置
List<int> ints = indexOf(byteCache.ToArray(), SplicSpace);
#region 以 分割符 分割 并解密对像数据 将解密后的数据保存到对像
///当前的 有用的 数据集合
List<byte[]> CurrentByteArrayCollection = new List<byte[]>();
//将当前对像保存到集合
for (int index = 0; index < ints.Count; index++)
{
#region 取出协意数据
//得到要跳过的数据
int skip = 0;// (index == 0 ? 0 : index);
//得到当前要取出的数据
//当前要取出的数据如果是第一次是就 ints中第一个的数据,第二次出现与以后的数据将会是
//当前出现的从位置减上一次出现的位置 减 协意拆分字符串长度
int take = (index == 0 ? ints[index] : ints[index] - ints[index - 1] - SplicSpace.Length);
///协意数据
byte[] protocolData = byteCache.Skip(skip).Take(take).ToArray();
#endregion
//添加到数据缓存集合
CurrentByteArrayCollection.Add(protocolData);
#region 从缓存队列中移除
//开始 提取数据并进行解密
foreach (byte byteSingle in protocolData)
{
//移除对像
byteCache.Dequeue();
}
//移除 分隔符号
foreach (byte splictbyte in SplicSpace)
{
//移除对像
byteCache.Dequeue();
}
#endregion
}
#endregion
foreach (byte[] byteProtocolData in CurrentByteArrayCollection)
{
//2010-11-25号 加入线程序调用方法
//定义线程池 的回调方法
if (ThreadPoolFun == null)
{
ThreadPoolFun = new System.Threading.WaitCallback((o) =>
{
//使用方法 将数据转到,接收器处理
ProtocolReceivedByThreadPool((byte[])o);
});
}
//将方法添加到线程池队列 提高效率
System.Threading.ThreadPool.QueueUserWorkItem(ThreadPoolFun, byteProtocolData);
}
CurrentByteArrayCollection = null;
ints = null;
}
}
}
#endregion
#region IProtocolReceiver 成员
/// <summary>
/// 注册事件
/// </summary>
/// <param name="_Param">参数</param>
protected void RegistOnProtocolReceived(string _Param)
{
if (OnProtocolReceived != null)
{
OnProtocolReceived(this, new RoutedPropertyChangedEventArgs<string>(null, _Param));
}
}
/// <summary>
/// 解完一包数据时
/// </summary>
public event RoutedPropertyChangedEventHandler<string> OnProtocolReceived;
/// <summary>
/// 反序列化对像时出现的异常
/// </summary>
public event RoutedPropertyChangedEventHandler<byte[]> DeserializeExceptioned;
#endregion
#region IProtocolReceiver 成员
/// <summary>
/// 清空缓存信息
/// </summary>
public void CacheClear()
{
byteCache.Clear();
}
#endregion
}