zoukankan      html  css  js  c++  java
  • 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次的接收。

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

  • 相关阅读:
    Android 进阶 Fragment 介绍和使用 (一)
    Android Activity 详述
    android 自定义组合控件 顶部导航栏
    android 开发进阶自定义控件 类似 TextView
    android 开发进阶 自定义控件-仿ios自动清除控件
    Android 在程序中动态添加 View 布局或控件
    Android ImageView 详述
    关于北京工作居住证相关问题
    Android中常用的5大布局详述
    关于北京计算机技术与软件专业技术资格(水平)考试(软考)报名及证书的领取
  • 原文地址:https://www.cnblogs.com/HelloQLQ/p/15135307.html
Copyright © 2011-2022 走看看