C#中流的解析和读取(拆包)

在客户端与服务端通信过程中,客户端通过TCP发送的数据包可能产生粘包。在读取的时候,当前的定义是包头添加数据包的长度,使用包头判断一个包的开始,通过流的当前位置读取包并截取要给完整的数据包,再把剩余的包返还到缓存数据区内。

MemoryStream ms = new MemoryStream(cache.ToArray());创建一个数据流;
BinaryReader br = new BinaryReader(ms);创建一个BinaryReader对象用来读取数据流;
public virtual int ReadInt32();从当前流中读取一个 4 字节有符号整数,并把流的当前位置往前移四个字节;
public virtual byte[] ReadBytes( int count );从当前流中读取指定数目的字节到一个字节数组中,并把流的当前位置往前移指定数目的字节。

流的当前位置的概念(ms.Position)
在这里插入图片描述

/// <summary>
/// 解析包,从缓冲区里取出一个完整的包
/// </summary>
/// <param name="cache"></param>
/// <returns></returns>
public static byte[] DecodePacket(ref List<byte> cache)
{
    if (cache.Count < 4)
    {
        return null;
    }

    using (MemoryStream ms = new MemoryStream(cache.ToArray()))
    {
        using (BinaryReader br = new BinaryReader(ms)) 
        {
            //包的长度(ReadInt32:读取一个4字节的带符号整数,并把流的位置向前移4个字节)
            int length = br.ReadInt32();
            //包的长度减去流的当前位置,用于判断包是否完整
            int remainLength = (int)(ms.Length - ms.Position);
            if (length > remainLength)
            {
                return null;
            }

            //读取数据,并且流的位置position向前移动length长度的字节
            byte[] data = br.ReadBytes(length);

            //更新数据缓存
            cache.Clear();
            //流的总长度减去流的当前位置position,是剩余流的长度
            int remainLengthAgain = (int)(ms.Length - ms.Position);
            cache.AddRange(br.ReadBytes(remainLengthAgain));

            return data;
        }
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值