Fork me on GitHub

C# Socket 封包 拆包 ProtoBuf 的使用

复制代码
//这是消息头包,消息头包大小是固定的,
//每次传输都要先传消息头,在传消息体
 enum EnumMsgType:消息类型
long PackgeSize:包大小
long TotalPackage:所有包总数
long PackageIndex:当前包索引

//消息体包
byte[] Data=null;不固定大小的包,大小在消息头包
复制代码

数据格式 用 ProtoBuf  比json转为byte后都要小。使用例子

https://blog.csdn.net/liehuo123/article/details/78408876

包头 包体 都转换为这个格式。

发送数据时必须 包头|包体|包头|包体的发送

 

主要是数据接受,我的思路是这样

我们可以在开发前自己算出 自己定义的包头大小,以后这个包头的大小都不会变化了。

首次接受,先按包头大小接受一次,能否通过ProtoBuf 转为包头实体,如果异常,说明该传包头的地方没传对,直接抛出异常,否则 得到包头实体

然后判断消息类型,假如是文件,我个人规定 该包头的首个包体是文件名,得到文件名

我们可以根据消息类型,封装不同的处理接受数据的方法,每次 接受某种消息类型的首个包头后,就在接下来用封装的方法完成这个消息余下的数据包括包头和包体。

接下来 while(packageIndex<TotalPackage){

 //包头实体接受到

//包体数据接受到

//更新packageIndex为当前包头的index

}

以上就是我自己的基于Socket 封包和拆包的思路,目前只是个思路,我这周看有机会实现一下不。

2021-08-17 修改

目前,我代码写好了,接收文件没问题了。

实现过程中,大体思路是对的,但是有点小问题。

1.包头和包体 都应该用struct变量,因为它们经过ProtoBuf序列化后,字节数更小一点。

2. 包头经过protobuf序列化,大小是不固定的,所以 我决定在用一个固定长度为4的byte数组存包头大小

3.一开始没有确定一个固定长度的包头的时候会出现粘包的情况,虽然可以sleep 个几百毫秒,大概率不会出现,但这种方式不稳定,效率低。

4.现在正确分包后,就可以不用sleep,每次接收先接收4个长度,计算出包头大小,比如为33,然后再接收33长度,转换成包头,在包头里找到包体长度,比如4096,然后再接收4096长度。这样一个被分的包接收完毕,进入一下次循环接收,每次循环都会进行这3次的接收。

 

最后,代码过段时间再贴出来。

 

posted @   HelloLLLLL  阅读(918)  评论(0编辑  收藏  举报
编辑推荐:
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· 卧槽!C 语言宏定义原来可以玩出这些花样?高手必看!
· langchain0.3教程:从0到1打造一个智能聊天机器人
点击右上角即可分享
微信分享提示