TCP组包

来源:互联网 发布:单片机串口通信原理 编辑:程序博客网 时间:2024/06/14 19:29
MemoryStream MemoryStream;                      //此类内存字节流int HEAD_LENGTH = 8;                             //包体长度字段+协议的唯一标识。其中前4个字节用来标识包体长度,后四个字节用来标识协议ID。byte[] buffer = new byte[1024*10];              //开辟10k大小的缓冲区,用于接收数据TcpClient client = null;byte[] lockObj = new byte[1];BinaryReader reader; // 初始化void Init(){    client = new TcpClient();    memoryStream = new MemoryStream()    reader = new BinaryReader(memoryStream);    client.BeginConnect(127.0.0.1, 8888, new AsyncCallback(OnConnected), null);}// 连接建立的回调函数void OnConnected(IAsyncResult result){    if(client.Connected)    {        client.GetStream().BeginRead(buffer, 0 , 1024*10, new AsyncCallback(OnReadData),null);    }    else    {        Debug.LogError("网络异常");    }}// 当读到数据void OnReadData(IAsyncResult result){    int dataLength = 0;    try    {        lock(lockObj)        {            dataLength = client.GetStream().EndRead(result);         }        // <span style="font-family: Arial, Helvetica, sans-serif;">组包处理</span>        GeneratePacket(buffer, dataLength);        // 继续读取        lock(lockObj)        {            // 首先要清空缓冲区            Array.Clear(buffer, 0, 1024*10);             // 然后读取            client.GetStream().BeginRead(buffer, 0, 1024*10, new AsyncCallback(OnReadData), null);        }    }    catch(Exception e)    {        Debug.LogError("网络异常");    }}// 组包处理 void GeneratePacket(byte[] bytes, int length)  {        memoryStream.Seek(0, SeekOrigin.End); // 文件末尾偏移0,即继续续写        memoryStream.Write(bytes, 0, length); // 写入length长度的数据        memoryStream.Seek(0, SeekOrigin.Begin); // 指针重置为0        // 数据包的长度        int dataLength = memoryStream.Length - memoryStream.Position;  //当前数据包的长度-指针的起始位置        while(dataLength >= HEAD_LENGTH)        {            UInt32 messageDataLen =  reader.ReadUInt32();   //这一步做完之后,memoryStream的Position,已经由原来位置,递增了4,因为reader读取4个字节            UInt32 protocolID = 0;            dataLength = memoryStream.Length - memoryStream.Position            if (dataLength >=messageDataLen+ 4) // 这里messageLen是数据部分,而+4,这个4protocolID占的四个字节             {                 protocolID = reader.ReadUInt32();                 MemoryStream tmpStream = new MemoryStream();                 BinaryWriter writer = new BinaryWriter(tmpStream);                 writer.Write(reader.ReadBytes(messageLen));                 tmpStream.Seek(0, SeekOrigin.Begin);                 HandleMessage(protocolID, tmpStream);             }             else //如果数据不够,那么因为上面第一次reader.ReadUInt32()的时候,Position,已经由原来位置,递增了4,所以要减去4             {                 memoryStream.Position = memoryStream.Position - 4;                 break;             }         }         dataLength = memoryStream.Length - memoryStream.Position;         byte[] remainBytes = reader.ReadBytes(dataLength);         memoryStream.SetLength(0);         memoryStream.Write(remainBytes, 0, remainBytes.Length); //将剩余的数据包向前搬移。}// 处理消息void HandleMessage(Uint32 protocolID, MemoryStream paramData){    /// do sth...}
0 0
原创粉丝点击