執行以上的批處理文件,將會在其目錄的上一層目錄下生成兩個源碼文件:Helloworld.pb.h和Helloworld.pb.cc.
將生成的這倆文件拖進工程里面去,至于vc的StdAfx,預編譯頭的問題,很好解決.在cc文件上點右鍵->屬性->C/C++->預編譯頭->預編譯頭(不使用預編譯頭),這事兒就妥妥的解決了.
以上就是ProtoBuf的基本用法了.
FlatBuffers支持將ProtoBuf的IDL轉換為自己的IDL,只需要簡單的一行命令:
flatc.exe --proto Helloworld.proto
該命令將會生成一個FlatBuffers的IDL文件:Helloworld.fbs.
Helloworld.fbs它看起來像是這樣的:
// Generated from Helloworld.proto
namespace fbs.helloworld;
table HelloWorld {
id:int = 0 (id: 0);
str:string (required, id: 1);
opt:int = 0 (id: 2);
}
// 定義之后將會提供GetHelloWorld,VerifyHelloWorldBuffer,FinishHelloWorldBuffer三個方法.
root_type HelloWorld;
這是我基于生成的IDL修改過的.
我們可以用下面這個bat去生成代碼:
flatc.exe --cpp -o ../ Helloworld.fbs
pause
執行之后,它將在當前目錄的上一層目錄下生成一個代碼文件:Helloworld_generated.h
使用方法大概是這樣的:
void testFlatBuffer()
{
//////////////////////////////////////////////////////////////////////////
// 編碼
//////////////////////////////////////////////////////////////////////////
flatbuffers::FlatBufferBuilder builder;
int32_t id = 10086;
const char *str = "hello world";
int32_t opt = 10000;
#if 0
auto strName = builder.CreateString(str);
auto root = fbs::helloworld::CreateHelloWorld(builder, id, strName, opt);
#else
auto root = fbs::helloworld::CreateHelloWorldDirect(builder, id, str, opt);
#endif
#if 0
builder.Finish(root);
#else
FinishHelloWorldBuffer(builder, root);
#endif
auto p = builder.GetBufferPointer();
auto sz = builder.GetSize();
auto bufferpointer =
reinterpret_cast<const char *>(builder.GetBufferPointer());
std::string buffer;
buffer.assign(bufferpointer, bufferpointer + builder.GetSize());
size_t n = buffer.length();
builder.ReleaseBufferPointer();
//////////////////////////////////////////////////////////////////////////
// 解碼
//////////////////////////////////////////////////////////////////////////
#if 0
auto decode = flatbuffers::GetRoot<proto::helloworld::HelloWorld>(buffer.c_str());
#else
auto decode = fbs::helloworld::GetHelloWorld(buffer.c_str());
#endif
assert(decode->id() == 10086);
assert( strcmp(decode->str()->c_str(), "hello world") == 0);
assert(decode->opt() == 10000);
}
ByteBuffer關于這個嘛,看以前的文章:http://www.shnenglu.com/tx7do/archive/2015/06/12/145865.html
協議定義如下:
#include "ByteBuffer.h"
// 聲明序列化
#define NET_APPEND(STRUCT_TYPE)\
static ByteBuffer& operator<<(ByteBuffer& lht, const STRUCT_TYPE& rht)
// 聲明解序列化
#define NET_READ(STRUCT_TYPE)\
static const ByteBuffer& operator>>(const ByteBuffer& lht, STRUCT_TYPE& rht)
namespace bb
{
namespace helloworld
{
struct CMD_HelloWorld
{
int32 id; // id
std::string str; // str
int32 opt; // optional field
CMD_HelloWorld()
{
this->id = 0;
this->opt = 0;
this->str.clear();
}
};
NET_APPEND(CMD_HelloWorld)
{
lht << rht.id
<< rht.str
<< rht.opt;
return lht;
};
NET_READ(CMD_HelloWorld)
{
lht >> rht.id
>> rht.str
>> rht.opt;
return lht;
};
}
}
使用的代碼是這樣的:
void testByteBuffer()
{
//////////////////////////////////////////////////////////////////////////
// 編碼
//////////////////////////////////////////////////////////////////////////
bb::helloworld::CMD_HelloWorld msg_encode;
msg_encode.id = 10086;
msg_encode.str = "hello world";
msg_encode.opt = 10000;
ByteBuffer sendBuffer;
sendBuffer.clear();
sendBuffer << msg_encode;
auto p = sendBuffer.contents();
auto sz = sendBuffer.size();
//////////////////////////////////////////////////////////////////////////
// 解碼
//////////////////////////////////////////////////////////////////////////
ByteBuffer recvBuffer;
recvBuffer.clear();
recvBuffer.append((uint8*)p, sz);
bb::helloworld::CMD_HelloWorld msg_decode;
recvBuffer >> msg_decode;
assert(msg_decode.id == 10086);
assert(strcmp(msg_decode.str.c_str(), "hello world") == 0);
assert(msg_decode.opt == 10000);
}
總結相比PB來說,FBS不需要額外的指定一個外部的緩存,它內置了一個緩存,大概這就是它快的緣故吧.
序列化之后的空間占用結果是:
protobuf:19 flatbuffers:48 bytebuffer:20.從空間上看,FBS是并不占優啊.
以前,一直使用的是ByteBuffer,因為簡單,而且無論是從空間上還是時間上都還算劃算.但是要手寫序列化的代碼,相對來說,比較煩人.所以還是PB,FBS這樣的利用IDL自動生成代碼的方式方便.
PB現在支持幾乎所有語言,是一個相當成熟的解決方案了.
FBS就目前來說,支持的語言并不多,官方只支持:C++
,Java
,C#
,Go
,Python
,JS
,C
,PHP
,Ruby.
PB的IDL各大編輯器幾乎都支持它的語法染色,然而FBS卻并沒有,這個看起來也很讓人蛋疼.
PB相對慢,但是空間占用小,它更適合外網傳輸,并且對時間并不是那么要求高的應用;
FBS相對快,但是空間占用較大,它在RPC,內網傳輸,以及對時間要求很高的場景上會很適合,在手機登移動平臺下,計算性能不高的場景下也是適合的.
總的來說,我要做網游的通訊協議,還是PB更加的適合.
FBS更適合的是Android,iOS這樣的移動平臺,因為它們對性能要求比較高,使用FBS能夠有效的提高性能.