1. 程式人生 > >protobuf-c 在arm linux 嵌入式平臺的使用 protobuf和Json對比測試

protobuf-c 在arm linux 嵌入式平臺的使用 protobuf和Json對比測試

        關於什麼是protobuf,網上搜搜一大堆,很多人用的都還是json,以為json是多種語言傳輸資料是萬能的,看完了protobuf的實現,就明白了簡單高效才是王道。

1、首先寫一個.proto副檔名的檔案json.proto,內容格式如下 message response {     required uint32 led_on=1;     required string node_id=2;     required string parent_id=3;     required string uuid=4;    }

./protoc-c json.proto

3、寫示例程式碼main.c:

解析:protobuf的核心就是pack和unpack以及最後的free_unpack,比如客戶端要給服務端傳送一個msg,客戶端把pack好的pBuf緩衝區資料直接發出去,服務端收到資料之後,再從pBuf裡面“取出”out結構體指標指向的msg,最後呼叫free_unpacked釋放out就可以了。

//main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "json.pb-c.h"

int main(void)
{
    Response msg,*out;
    unsigned char *pBuf;
    unsigned int Len;
    response__init(&msg);            //init default

    msg.led_on=1;
    msg.node_id="5149013220584027";
    msg.parent_id="5149013108519750";
    msg.uuid="121212121";

    Len=response__get_packed_size(&msg);

    printf("msg pack size %d\n",Len);

    pBuf=malloc(Len);
    if(pBuf)
    {
        response__pack(&msg,pBuf);        //construct msg to pBuf
        FILE *fp =fopen("protobuf.txt","wb+");        //output raw
        if(fp)
        {
            fwrite(pBuf,Len,1,fp);
            fclose(fp);
            fp=NULL;
        }

        out=response__unpack(NULL,Len,pBuf);
        if(out)
        {
            printf("out->led_on=%d\n",((Response*)out)->led_on);
            printf("out->node_id=%s\n",((Response*)out)->node_id);
            printf("out->parent_id=%s\n",((Response*)out)->parent_id);
            printf("out->uuid=%s\n",((Response*)out)->uuid);
            response__free_unpacked(out,NULL);
        }
    }

    printf("End\n");
}

4、編譯註意事項
注意相關標頭檔案所在目錄為./protobuf-c/protobuf-c.h,相關libprotobuf-c.so庫檔案所在路徑為./protobuf-c-arm/lib

5、編譯,最終生成main可執行檔案,將main放在開發板上,注意,相關的libc庫和libprotobuf-c.so連結庫都放在了開發板上/usr/arm-linux-gnueabi/lib目錄下,否則執行是找不到.so庫的 arm-linux-gnueabi-gcc main.c -o main json.pb-c.c -I./ -lprotobuf-c -L./protobuf-c-arm/lib -Wl,-rpath,/usr/arm-linux-gnueabi/lib

6、執行./main 實現了msg訊息傳送給out輸出,同樣型別的訊息,Json需要91個位元組,protobuf只需要49個位元組,其實json裡面的鍵值對name是完全不需要傳輸的,因為通訊雙方都知道對應的name,只需要傳輸的只是value,但是每次傳輸資料,都要把name都傳來傳去,消耗了大量的頻寬和資料儲存空間 下面是測試結果

附錄:
1、經過測試,我們發現,其實protobuf的原理很簡單,和兩端都是C語言實現的client/server直接傳輸結構體變數原理是一樣的,我們都知道,C語言結構體成員的儲存方式都是順序儲存。所以傳送和接收方都按照對應的成員排列位置進行解析,就可以實現資料的傳輸。 2、但是protobuf設計初衷應該是為了適應不同的語言之間資料傳輸,像java寫的server裡面就沒有結構體,所以就不能傳輸C寫的client裡面的結構體變數給對方,對方是解析不了的。另外protobuf在.proto檔案裡面指定了具體的位置編號,否則應該就沒辦法生成.c和.h檔案,如果後續雙方通訊格式要做調整,雙方都使用同一個修改後的.proto檔案重新生產對應的原始檔,重新編譯即可。 3、為什麼說用protobuf比json簡單高效,原因就是你用json傳輸資料,每次字串裡面都傳輸了一堆沒用的資料,比如鍵值對的冒號,以及鍵值名字和值的雙引號,還有大小括號,因為通訊雙方都知道對應的鍵值名以及怎麼解析json(如果不知道鍵值名字,收到的資料還怎麼解析?)。 雙方都有的資料還每次傳來傳去,不是浪費是什麼? 純粹就是浪費頻寬和儲存,要傳輸的對方沒有的資料,這才是有用資料。有人就說,這幾個括號和鍵值名字能浪費多少頻寬和空間,別小看這些小東西,假如資料互動量大和非常頻繁,你就知道了,這裡面的儲存空間和頻寬消耗差距是可怕驚人的。


4、最後不得不佩服,google出品必屬精品。