配置python-protobuf解析環(huán)境

protobuf是一種跨語言協(xié)議账嚎,不同語言之間只需定義同一份proto文件克滴,即可實現(xiàn)不同種類的語言的協(xié)議溝通。由于工作中使用c++解碼較為麻煩熄驼,為了提升工作效率像寒,想通過python達到快速解析pb數(shù)據(jù)的目的(系統(tǒng)為macOS Sierra)。

image.png

出自文章 https://segmentfault.com/a/1190000010098194

python版本的protobuf安裝

首先安裝官方protobuf瓜贾,通過執(zhí)行protoc命令诺祸,可以將proto源文件編譯成對應語言的數(shù)據(jù)結構文件和解析代碼,如python對應的文件后綴名通常為.py和.pyc祭芦;官方下載鏈接:https://github.com/google/protobuf/releases序臂,下載全量源碼,然后解壓实束、安裝奥秆,然后確認安裝是否成功。此外可以通過 brew install protobuf 直接安裝咸灿。

cd 對應目錄
./configure 
make 
make check 
make install
protoc --version

其次构订,安裝對應的python protobuf模塊,python引入該模塊即可編寫代碼避矢,實現(xiàn)pb文件的解析悼瘾。安裝python protobuf模塊囊榜,首先安裝pip,mac系統(tǒng)的python自帶easy_install亥宿,因此直接輸入命令:sudo easy_install pip卸勺;再通過pip來安裝protobuf,命令:pip install protobuf烫扼;
遇到的問題:mac下python的six模塊版本較低曙求,且由于系統(tǒng)原因,無法被卸載安裝新版映企,而pip在安裝protobuf時需要悟狱,默認會下載安裝較新版本的six模塊,因此這里出現(xiàn)了沖突堰氓。通過參考該鏈接:https://github.com/pypa/pip/issues/3165挤渐,只需在使用pip安裝python模塊前,執(zhí)行該命令即可:

pip install --ignore-installed six

使用python解析pb數(shù)據(jù)流程

這里使用c++對數(shù)據(jù)進行編碼双絮,并生成pb二進制文件浴麻,再通過python對pb二進制文件解碼,得到c++輸入的數(shù)據(jù)囤攀。使用c++寫的client程序和python寫的server服務器程序通信软免,在cleint端對數(shù)據(jù)編碼,在server端對數(shù)據(jù)解碼抚岗,通信方式采用socket,通信數(shù)據(jù)格式采用protobuf哪怔。

遇到的問題:當c++客戶端-c++服務器宣蔚,數(shù)據(jù)能正常編碼和解析,而c++客戶端-python服務器時认境,服務端python的recv函數(shù)接收的數(shù)據(jù)是null胚委,無法正常接收。

解決方案:懷疑是python接收二進制數(shù)據(jù)問題叉信,具體原因后續(xù)探究亩冬。因此把c++編碼的protobuf數(shù)據(jù)再進行base64編碼,將二進制proto數(shù)據(jù)變?yōu)樽址鹕恚攑ython服務端收到數(shù)據(jù)后硅急,先進行base64解碼,再對protobuf數(shù)據(jù)解碼佳遂。

people.proto源文件:

package demo;
message People {  
  required string name = 1;  
  required int32 id = 2;  
  required string email = 3;  
}

切換到對應的proto源文件目錄营袜,執(zhí)行命令,將產(chǎn)出兩個文件people.pb.cc 和people.pb.h

protoc -I . --c++_out=. people.proto

切換到對應的proto源文件目錄丑罪,執(zhí)行以下命令荚板,將產(chǎn)出文件people_pb2.pyc

protoc -I . --python_out=. people.proto

c++客戶端代碼:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <iostream>
#include "people.pb.h"http://引入c++對應的proto文件
#include "base64.h"
#define MYPORT  8080
#define BUFFER_SIZE 1024
int main()
{
    ///定義sockfd
    int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
    
    ///定義sockaddr_in
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(MYPORT);  ///服務器端口
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  ///服務器ip
    
    ///連接服務器凤壁,成功返回0,錯誤返回-1
    if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("connect");
        exit(1);
    }
    
    char recvbuf[BUFFER_SIZE];
    char sendbuf[BUFFER_SIZE];
    int numbytes = (int)recv(sock_cli, recvbuf, BUFFER_SIZE, 0);
    recvbuf[numbytes] = '\0';
    std::string strbuf = recvbuf;
    std::cout << "Client Message: " << strbuf << std::endl;
    if(strbuf == "GET PEOPLE")
    {
        std::string data;
        demo::People p;
        p.set_name("xionghengheng");
        p.set_id(1881409);
        p.set_email("xionghengheng@gmail.com");
        p.SerializeToString(&data);//protobuf數(shù)據(jù)編碼
        char bts[data.length()];
        strcpy(bts, data.c_str());
        Base64 *base64 = new Base64();
        std::string encode = base64->Encode((unsigned char*)bts, data.length());//base64編碼
        memset(sendbuf, 0, sizeof(sendbuf));
        strcpy(sendbuf, encode.c_str());
        send(sock_cli, sendbuf, strlen(sendbuf), 0);
    }
    else
    {
        send(sock_cli, "Fucking client!\n", 16, 0);
    }
    memset(recvbuf, 0, sizeof(recvbuf));
    close(sock_cli);
    return 0;
}

python2.7服務端程序:

# -*- coding: UTF-8 -*-
import os
import socket
import time
import threading
import people_pb2 as people#引入python proto對應的文件
import base64
def tcplink(sock, addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send('GET PEOPLE'.encode())
    while True:
        data = sock.recv(2048)
        time.sleep(1)
        if data == 'exit' or not data:
            print("no data")
            break
        else:
            data = base64.b64decode(data)#base64解碼
            peopleItem = people.People()
            peopleItem.ParseFromString(data)#protobuf數(shù)據(jù)解碼
            print(peopleItem.name)
            print(peopleItem.id)
            print(peopleItem.email)
    sock.close()
    print('Connection from %s:%s closed.' % addr)
# 開啟ip和端口
ip_port = ('127.0.0.1', 8080)
# 生成句柄
web = socket.socket()
# 綁定端口
web.bind(ip_port)
# 最多連接數(shù)
web.listen(5)
# 等待信息
print ('nginx waiting...')
# 開啟死循環(huán)
while True:
    # 接受一個新連接:
    sock,addr = web.accept()
    # 創(chuàng)建新線程來處理TCP連接:
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()

服務端輸出結果:

nginx waiting...
Accept new connection from 127.0.0.1:50828...
xionghengheng
1881409
xionghengheng@gmail.com
no data
Connection from 127.0.0.1:50828 closed.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末跪另,一起剝皮案震驚了整個濱河市拧抖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌免绿,老刑警劉巖唧席,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異针姿,居然都是意外死亡袱吆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門距淫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绞绒,“玉大人,你說我怎么就攤上這事榕暇∨詈猓” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵彤枢,是天一觀的道長狰晚。 經(jīng)常有香客問我,道長缴啡,這世上最難降的妖魔是什么壁晒? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮业栅,結果婚禮上秒咐,老公的妹妹穿的比我還像新娘。我一直安慰自己碘裕,他們只是感情好携取,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帮孔,像睡著了一般雷滋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上文兢,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天晤斩,我揣著相機與錄音,去河邊找鬼姆坚。 笑死尸昧,一個胖子當著我的面吹牛,可吹牛的內容都是我干的旷偿。 我是一名探鬼主播烹俗,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼爆侣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了幢妄?” 一聲冷哼從身側響起兔仰,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕉鸳,沒想到半個月后乎赴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡潮尝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年榕吼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勉失。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡羹蚣,死狀恐怖,靈堂內的尸體忽然破棺而出乱凿,到底是詐尸還是另有隱情顽素,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布徒蟆,位于F島的核電站胁出,受9級特大地震影響,放射性物質發(fā)生泄漏段审。R本人自食惡果不足惜全蝶,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寺枉。 院中可真熱鬧抑淫,春花似錦、人聲如沸型凳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甘畅。三九已至,卻和暖如春往弓,著一層夾襖步出監(jiān)牢的瞬間疏唾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工函似, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留槐脏,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓撇寞,卻偏偏與公主長得像顿天,于是被迫代替她去往敵國和親堂氯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容