最近在项目中使用谷歌的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#文件,由于生成的文件过长,在此处就没有贴出代码了
不过在序列化成Utf-8的时候,反序列化回来就直接报错,如果用byte或者Unicode序列化就没问题
/// <summary>
/// 序列化测试
/// </summary>
[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());
}
执行过后的结果是:
感觉是int溢出,测试发现RequestMsgData中的int类型最多只支持8位,也就是说我int类型的数据,赋值大于127的话,字符串反序列化回来就会有问题,这个确实百思不得其解。。。
如果用Unicode编码的话就不会有问题,用utf-32反序列化不通过。。。。
现在的项目背景是:服务端C++也是用probuf中字符串接收我的,他们直接用SerializeAsString方法即可直接将对象序列化为对应的字符串,而C#中没看到有现成的序列化方法。
最后小弟插个话:不知道谁在实际项目中遇到类似的问题,需要交流的可以加464010942