Google.Protobuf和protoBuf-net中utf-8反序列化问题

最近在项目中使用谷歌的protoBuf协议做数据传输,.proto文件中定义的数据类型如下

syntax = "proto3";

package ykcz_msg;

/*消息类型---格式"MSGYTPE_模块_REQ/RPY_操作,不同模块消息分段"
* 消息号定义:同个模块的消息“万位相同,回报消息是对应请求消息+5000”,比如请求登陆是“10001”,那么登陆回报就是“15001”
*/
enum MsgType
{
	//无类型
	MSGTYPE_NO=0;

	/***********交易请求类型***********/
	//请求登陆
	MSGYTPE_TRADE_REQ_LOGIN=10001;


	
	/***********历史查询请求类型***********/
	//请求登陆回报
	MSGTYPE_TRADE_RPY_LOGIN=15001;



}

//请求消息
message RequestMsgData
{
	//请求消息类型
	int32 req_type = 1;
    //请求消息具体内容
	bytes req_body=2;
	//客户ID
	bytes client_id = 3;
	//请求客户端连接uuid---回报消息用
	bytes client_conn_uuid = 4;
	//请求的上级客户端连接uuid---回报消息用
	bytes sub_client_conn_uuid = 5;
	//请求编号(应用层保证每次请求递增且唯一,非必填)
	int32 req_no=6;
	//用户登陆token
	bytes client_login_token=7;
	//请求预留字段,格式"key=value;key=value;",非必填;
	bytes req_extends=8;
	//协议版本号
	bytes version = 9;
}

//回报消息
message ResponseMsgData
{
	//回报消息类型
	int32 reply_type = 1;
    //回报消息具体内容(数组)
	repeated bytes reply_body_array=2;  
	//客户ID
	bytes client_id=3;
	//请求的上级客户端连接uuid---回报消息用
	bytes sub_client_conn_uuid = 4; 
	//回报的请求编号
	int32 reply_req_no=5;
	//回报预留字段,格式"key=value;key=value;",非必填;
	bytes reply_extends=6;
	//错误id,0成功,其它是错误码
    int32 error_no=7;
	//错误的具体信息
    bytes error_info=8; 
	//大包拆包的总包数量
	int32 package_total_num=9;
	//大包拆包的当前包序号
	int32 package_curr_num=10;
	//协议版本号
	bytes version = 11; 
}

//测试消息
message TestData
{
	int32 nData1=1;
	int32 nData2=2;
	int32 nData3=3;
	int32 nData4=4;
	int32 nData5=5;
	int32 nData6=6;
	int32 nData7=7;
	int32 nData8=8;
	int32 nData9=9;
	int32 nData10=10;
	double dData1=11;
	double dData2=12;
	double dData3=13;
	double dData4=14;
	double dData5=15;
	double dData6=16;
	double dData7=17;
	double dData8=18;
	double dData9=19;
	double dData10=20;
	string strData1=21;
	string strData2=22;
	string strData3=23;
	string strData4=24;
	string strData5=25;
	string strData6=26;
	string strData7=27;
	string strData8=28;
	string strData9=29;
	string strData10=30;
}

 如何用.proto文件生成对应的C#代码,下面我贴出对protoBuf-net中的git,上面有对应的一些说明,希望能帮到大家!

protobuf-net:https://github.com/protobuf-net/protobuf-net

protogen:https://protogen.marcgravell.com/

我项目中的生成代码是用ProtoBuf工具生成的,直接去NtGet搜索即可,然后按照下面就能生成对应的C#文件,由于生成的文件过长,在此处就没有贴出代码了Google.Protobuf和protoBuf-net中utf-8反序列化问题_第1张图片

Google.Protobuf和protoBuf-net中utf-8反序列化问题_第2张图片

Google.Protobuf和protoBuf-net中utf-8反序列化问题_第3张图片


 

不过在序列化成Utf-8的时候,反序列化回来就直接报错,如果用byte或者Unicode序列化就没问题

  /// 
        /// 序列化测试
        /// 
        [TestMethod]
        public void ProtoBufSerial()
        {
            RequestMsgData request_data = new RequestMsgData();
            request_data.ClientConnUuid = ByteString.CopyFromUtf8(Guid.NewGuid().ToString("N"));
            request_data.ReqNo = 1500;
            request_data.ReqType = 2500000;
            request_data.ReqBody = ByteString.CopyFromUtf8($"I am client{1}");
            var bytes = new byte[request_data.CalculateSize()];
            Debug.WriteLine("原始值");
            Debug.WriteLine(request_data.ToString());
            var str = string.Empty;
            //序列化
            using (CodedOutputStream cos = new CodedOutputStream(bytes))
            {
                request_data.WriteTo(cos);
                str = Encoding.UTF8.GetString(bytes);
                Debug.WriteLine(str);
            }


            //反序列化
            Debug.WriteLine("byte反序列化");
            var deMsg = RequestMsgData.Parser.ParseFrom(bytes);
            Debug.WriteLine(deMsg.ToString());

            Debug.WriteLine("str反序列化");
            var bytes1 = Encoding.UTF8.GetBytes(str);
            var deMsg_1 = RequestMsgData.Parser.ParseFrom(bytes1);
            Debug.WriteLine(deMsg_1.ToString());

        }

执行过后的结果是:

Google.Protobuf和protoBuf-net中utf-8反序列化问题_第4张图片

感觉是int溢出,测试发现RequestMsgData中的int类型最多只支持8位,也就是说我int类型的数据,赋值大于127的话,字符串反序列化回来就会有问题,这个确实百思不得其解。。。

Google.Protobuf和protoBuf-net中utf-8反序列化问题_第5张图片

如果用Unicode编码的话就不会有问题,用utf-32反序列化不通过。。。。


 

现在的项目背景是:服务端C++也是用probuf中字符串接收我的,他们直接用SerializeAsString方法即可直接将对象序列化为对应的字符串,而C#中没看到有现成的序列化方法。

最后小弟插个话:不知道谁在实际项目中遇到类似的问题,需要交流的可以加464010942

你可能感兴趣的:(ProtoBuf,protobuf,c#)