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#文件,由於生成的文件過長,在此處就沒有貼出代碼了


 

不過在序列化成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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章