1. 程式人生 > >python處理Protoc Buffers協議下的header+protobuf

python處理Protoc Buffers協議下的header+protobuf

專案中碰到了tcp透傳下用protocol buffer協議的資料傳輸場景
記錄下踩的坑~~

協議的定義大致舉例如下:

資料傳輸協議組成部分分為header結構體和一個傳輸資料message體

header如下,其中某個param是需要擷取的message包體長度(如這裡是param_3)

struct header
{ 
unsigned short param_1; // 頭資訊定義引數1
unsigned short param_2; // 頭資訊定義引數2
unsigned short param_3; // 頭資訊定義引數3
} 

message的結構為:

message request_params
{ 
optional uint64 param_4 = 1; // 引數4
optional string param_5 = 2; // 引數5
}

介面拿到的是二進位制流,需要實現的步驟如下大致如下:
將拿到的二進位制流轉換到十六進位制流hex_data(根據協議定義,位元組擷取是在十六進位制下進行);

data = self.request.recv(10000)
data2 = data.encode('hex')

根據協議在約定的位元組區間擷取header中的param_3,這個值是後邊需要擷取的資料包位元組長度,然後將param_3轉換成二進位制下的整型數字param_3_int;從header資訊結束位元組處開始,擷取hex_data中長度為param_3_int*2的位元組段;

param_3 = data2[x:y]
data4 = (int(str(param_3), 16)) * 2
data5 = data2[y:y + data4

將擷取的位元組段重新轉換成二進位制流;

data6 = binascii.a2b_hex(data5)

然後用protoc的方法解析出來;

req = request_params()
req.ParseFromString(data6)
json_str = protobuf_json.pb2json(req)

解析後是一個json格式的資料體了,如果這個資料體內還有json物件需要取,可能需要將單引號轉換為雙引號,將多於的無效字元清除,然後再loads資料,如下:

data = data.replace('\'', '\"')
data = data.rstrip('\x00')
loaded_data = json.loads(data)