using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace NetFramework
{
/// <summary>
/// 计算机如何存储大数值的体系结构
/// </summary>
public enum Endian
{
/// <summary>
/// Intel x86,AMD64,DEC VAX
/// </summary>
LITTLE_ENDIAN = ,
/// <summary>
/// Sun SPARC, Motorola 68000,Java Virtual Machine
/// </summary>
BIG_ENDIAN = ,
} public class ReceiveQueue
{
#region zh-CHS 类常量 | en Class Constants
/// <summary>
/// 字节默认的大小
/// </summary>
private const long BUFFER_SIZE = * ;
#endregion #region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 字节的头位置
/// </summary>
private long m_Head;
/// <summary>
/// 字节的尾位置
/// </summary>
private long m_Tail;
/// <summary>
/// 字节的数组
/// </summary>
private byte[] m_Buffer = new byte[BUFFER_SIZE];
/// <summary>
///
/// </summary>
private object m_LockBuffer = new object();
#endregion #region zh-CHS 属性 | en Properties
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 字节的大小
/// </summary>
private long m_Size;
#endregion
/// <summary>
/// 环绕缓冲区内的数据大小
/// </summary>
public long Length
{
get { return m_Size; }
} #endregion #region zh-CHS 方法 | en Method
/// <summary>
/// 给出使用环绕缓冲区内的数据
/// </summary>
/// <param name="byteBuffer">要复制到的数据的数组</param>
/// <param name="iOffset">要复制到数组的长度偏移量</param>
/// <param name="iSize">要复制多少长度的数据</param>
/// <returns>返回实际读取到的字节数</returns>
public long Dequeue(byte[] byteBuffer, long iOffset, long iSize)
{
if (byteBuffer == null)
throw new ArgumentNullException("byteBuffer", "ReceiveQueue.Dequeue(...) - byteBuffer == null error!"); if (iOffset < || iOffset >= byteBuffer.Length)
throw new Exception("ReceiveQueue.Dequeue(...) - iOffset < 0 || iOffset >= byteBuffer.Length error!"); if (iSize < || iSize > byteBuffer.Length) // 如果iLength == 0就返回空,如果iLength == 0就跳过
throw new Exception("ReceiveQueue.Dequeue(...) - iSize < 0 || iSize > byteBuffer.Length error!"); if ((byteBuffer.Length - iOffset) < iSize)
throw new Exception("ReceiveQueue.Dequeue(...) - ( byteBuffer.Length - iOffset ) < iSize error!"); if (iSize == )
return ; lock (m_LockBuffer)
{
if (iSize > m_Size)
iSize = m_Size; if (m_Head < m_Tail)
Buffer.BlockCopy(m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)iSize);
else
{
long rightLength = m_Buffer.Length - m_Head; if (rightLength >= iSize)
Buffer.BlockCopy(m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)iSize);
else
{
Buffer.BlockCopy(m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)rightLength);
Buffer.BlockCopy(m_Buffer, , byteBuffer, (int)(iOffset + rightLength), (int)(iSize - rightLength));
}
} m_Head = (m_Head + iSize) % m_Buffer.Length;
m_Size -= iSize; if (m_Size == )
{
m_Head = ;
m_Tail = ;
}
} return iSize;
} /// <summary>
/// 压入数据至环绕缓冲区内
/// </summary>
/// <param name="byteBuffer"></param>
/// <param name="iOffset"></param>
/// <param name="iSize"></param>
public void Enqueue(byte[] byteBuffer, long iOffset, long iSize)
{
if (byteBuffer == null)
throw new ArgumentNullException("byteBuffer", "ReceiveQueue.Enqueue(...) - byteBuffer == null error!"); if (iOffset < || iOffset >= byteBuffer.Length)
throw new Exception("ReceiveQueue.Enqueue(...) - iOffset < 0 || iOffset >= byteBuffer.Length error!"); if (iSize < || iSize > byteBuffer.Length) // 如果iLength == 0就返回空,如果iLength == 0就跳过
throw new Exception("ReceiveQueue.Enqueue(...) - iSize < 0 || iSize > byteBuffer.Length error!"); if ((byteBuffer.Length - iOffset) < iSize)
throw new Exception("ReceiveQueue.Enqueue(...) - ( byteBuffer.Length - iOffset ) < iSize error!"); lock (m_LockBuffer)
{
if ((m_Size + iSize) >= m_Buffer.Length)
SetCapacityInLock((m_Size + iSize + ) & ~); // 总是以2048的倍数来增大字节数, :( 弄得我老半天才明白原理呢! if (m_Head < m_Tail)
{
long rightLength = m_Buffer.Length - m_Tail; if (rightLength >= iSize)
Buffer.BlockCopy(byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)iSize);
else
{
Buffer.BlockCopy(byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)rightLength);
Buffer.BlockCopy(byteBuffer, (int)(iOffset + rightLength), m_Buffer, , (int)(iSize - rightLength));
}
}
else
Buffer.BlockCopy(byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)iSize); m_Tail = (m_Tail + iSize) % m_Buffer.Length;
m_Size += iSize;
}
} /// <summary>
/// 清除数据的信息,不清除数据缓冲,用于下次使用
/// </summary>
public void Clear()
{
lock (m_LockBuffer)
{
m_Head = ;
m_Tail = ;
m_Size = ;
} } /// <summary>
///
/// </summary>
private Endian m_Endian = Endian.BIG_ENDIAN; /// <summary>
/// 包的长度
/// </summary>
public const int PacketLengthSize = ; /// <summary>
/// 包的长度
/// </summary>
public const int PacketHeadLengthSize = ; /// <summary>
/// 给出数据包的长度
/// </summary>
/// <returns></returns>
public int GetPacketLength()
{
int iReturn = ; lock (m_LockBuffer)
{
if (PacketLengthSize > m_Size)
return ; if (m_Head + PacketLengthSize < m_Buffer.Length)
{
// 保证要读取的数据在字节数组里
var index = m_Head; // 读四字节长度
if (m_Endian == Endian.LITTLE_ENDIAN)
return (m_Buffer[index] << ) | (m_Buffer[index+] << ) | (m_Buffer[index+] << ) | m_Buffer[index+];
else
return m_Buffer[index] | (m_Buffer[index + ] << ) | (m_Buffer[index + ] << ) | (m_Buffer[index + ] << ); //if (m_Endian == Endian.LITTLE_ENDIAN)
// return (m_Buffer[index] << 8) | (m_Buffer[index + 1]);
//else
// return m_Buffer[index] | (m_Buffer[index + 1] << 8);
}
} return iReturn;
} /// <summary>
/// 给出数据包头部的长度
/// </summary>
/// <returns></returns>
public int GetPacketHeadLength()
{
int iReturn = ; lock (m_LockBuffer)
{
if (PacketLengthSize + PacketHeadLengthSize > m_Size)
return ; if (m_Head + PacketLengthSize + PacketHeadLengthSize < m_Buffer.Length)
{
// 保证要读取的数据在字节数组里
var index = m_Head + PacketLengthSize; // 读四字节长度
if (m_Endian == Endian.LITTLE_ENDIAN)
return (m_Buffer[index] << ) | (m_Buffer[index + ] << ) | (m_Buffer[index + ] << ) | m_Buffer[index + ];
else
return m_Buffer[index] | (m_Buffer[index + ] << ) | (m_Buffer[index + ] << ) | (m_Buffer[index + ] << ); //if (m_Endian == Endian.LITTLE_ENDIAN)
// return (m_Buffer[index] << 8) | (m_Buffer[index + 1]);
//else
// return m_Buffer[index] | (m_Buffer[index + 1] << 8);
}
} return iReturn;
} #endregion #region zh-CHS 私有方法 | en Private Method
/// <summary>
/// 扩大缓冲数据的大小(当前都在锁中操作,因此不需要锁定的)
/// </summary>
/// <param name="iCapacity"></param>
private void SetCapacityInLock(long iCapacity)
{
byte[] newBuffer = new byte[iCapacity]; if (m_Size > )
{
if (m_Head < m_Tail)
Buffer.BlockCopy(m_Buffer, (int)m_Head, newBuffer, , (int)m_Size);
else
{
long rightLength = m_Buffer.Length - m_Head; Buffer.BlockCopy(m_Buffer, (int)m_Head, newBuffer, , (int)rightLength);
Buffer.BlockCopy(m_Buffer, , newBuffer, (int)rightLength, (int)m_Tail);
}
} m_Head = ;
m_Tail = m_Size;
m_Buffer = newBuffer;
}
#endregion
}
}
while (true)
{
if (e.ReceiveBuffer != null)
{
data = new byte[e.BytesReceived];
Array.Copy(e.ReceiveBuffer, e.Offset, data, , e.BytesReceived);
nMsgLen = e.BytesReceived;
}
if (nMsgLen <= )
{
break;
} if (package_len > && head_len > )
{
e.ReceiveBufferQueue.Enqueue(data, , e.BytesReceived);
if (e.ReceiveBufferQueue.Length == package_len + )
{
lock (this)
{
package_len = ;
head_len = ;
byte[] temp = new byte[e.ReceiveBufferQueue.Length];
int len = (int)e.ReceiveBufferQueue.Dequeue(temp, , e.ReceiveBufferQueue.Length);
ExecGateBuffers(GateIdx, Gate, temp, len);
M2Share.MainOutMessage(string.Format("=========={0}", len));
break;
}
}
} if (package_len > && head_len == )
{
Array.Reverse(data);
e.ReceiveBufferQueue.Enqueue(data, , e.BytesReceived);
head_len = e.ReceiveBufferQueue.GetPacketHeadLength();
M2Share.MainOutMessage(string.Format("head_len : {0}", head_len));
} if (package_len == )
{
Array.Reverse(data);
e.ReceiveBufferQueue.Enqueue(data, , e.BytesReceived);
package_len = e.ReceiveBufferQueue.GetPacketLength();
M2Share.MainOutMessage(string.Format("package_len : {0}", package_len));
}
break;
}

ReceiveQueue的更多相关文章

  1. twitter storm 源码走读之5 -- worker进程内部消息传递处理和数据结构分析

    欢迎转载,转载请注明出处,徽沪一郎. 本文从外部消息在worker进程内部的转化,传递及处理过程入手,一步步分析在worker-data中的数据项存在的原因和意义.试图从代码实现的角度来回答,如果是从 ...

  2. twitter storm源码走读之3--topology提交过程分析

    概要 storm cluster可以想像成为一个工厂,nimbus主要负责从外部接收订单和任务分配.除了从外部接单,nimbus还要将这些外部订单转换成为内部工作分配,这个时候nimbus充当了调度室 ...

  3. Twitter Storm中Bolt消息传递路径之源码解读

    本文初次发表于storm-cn的google groups中,现以blog的方式再次发表,表明本人徽沪一郎确实读过这些代码,:). Bolt作为task被executor执行,而executor是一个 ...

  4. worker启动executor源码分析-executor.clj

    在"supervisor启动worker源码分析-worker.clj"一文中,我们详细讲解了worker是如何初始化的.主要通过调用mk-worker函数实现的.在启动worke ...

  5. procfs

    https://www.kernel.org/doc/Documentation/filesystems/proc.txt /proc/stat cpu 493610 1050 955506 6140 ...

  6. Storm系列(十六)架构分析之Executor-Bolt

    准备消息循环的数据 函数原型: 1  let[executor-sampler (mk-stats-sampler (:storm-conf executor-data))] 主要功能: 定义tupl ...

  7. Storm系列(十五)架构分析之Executor-Spout

    Spout实现mk-threads接口用于创建与Executor对应的消息循环主函数. defmulti mk-threads executor-selector Mk-threads函数的主消息循环 ...

  8. Storm系列(十四)架构分析之Executor-输入和输出处理

    Executor的数据 mk-executor-data函数用于定义Executor中含有的数据. Executor的输入处理 根据executor-id从Worker的:executor-recei ...

  9. STORM在线业务实践-集群空闲CPU飙高问题排查

    源:http://daiwa.ninja/index.php/2015/07/18/storm-cpu-overload/ 2015-07-18AUTHORDAIWA STORM在线业务实践-集群空闲 ...

随机推荐

  1. homebrew update 出现Failure while executing: git pull --quiet origin refs/heads/master:refs/remotes/origin/master解决方案

    具体可以参考https://github.com/Homebrew/homebrew/issues/21002 cd /usr/local git status git reset --hard or ...

  2. java基础

    属性是对象的特征,每个对象都有自己独立的属性值.一个对象的属性发生变化,不会影响另外一个对象的属性.属性是封装在对象之中的变量,是对象的成员.属性也叫成员变量. null表示一个变量没有指向任何对象. ...

  3. 阮一峰对js的见解(10大缺陷)

    一.为什么Javascript有设计缺陷?这里有三个客观原因,导致Javascript的设计不够完善.1. 设计阶段过于仓促Javascript的设计,其实只用了十天.而且,设计师是为了向公司交差,本 ...

  4. 浅谈SQL Transaction在请求中断后的行锁表锁

    最近在维护Web Service接口时,由于数据数据量达到千万级别,接口调用不时出现错误让人不胜烦恼,经过性能测试查出瓶颈在数据库数据处理上,可着实忙了一番.相信众多程序猿和DBA都会头痛性能的问题, ...

  5. 解决IE6/IE7/IE8不支持before,after问题

    对从事web开发的朋友来讲,低版本的IE永远是一个痛点,不支持最新技术(如css3,html5). 在现在web开发中使用图标字体已经很广泛,如Font Awesome,Bootstrap等,字体图片 ...

  6. DirectX游戏编程(一):创建一个Direct3D程序

    一.环境 Visual Studio 2012,DirectX SDK (June 2010) 二.准备 1.环境变量(如没有配置请添加) 变量名:DXSDK_DIR 变量值:D:\Software\ ...

  7. TPC-H生成.tbl文件导入postgresql数据库的坑

    数据库project好好的不用主流的MySQL和Microsoft server而要求用听都没听过的postgresql (当然,可能你三个都没听过) 这里的坑主要是把生成的那八张.tbl的表导入pg ...

  8. *HDU 1115 计算几何

    Lifting the Stone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  9. ThinkPHP5 助手函数

    对于ThinkPHP5.0以前的版本,助手函数全部是单字母函数,但到ThinkPHP5之后,使用如下函数来代替单字母函数: 最常用: /** * 实例化Model * @param string $n ...

  10. unity3D学习—坦克大战(一)

    背景介绍 本人一名C#程序员,从事C#开发已经有四年有余了,目前在一家大型公司上班.鉴于公司的业务需要,现在需要学习unity3D游戏开发,好在unity支持C#脚本开发,无形中省下了许多重新学习新语 ...