有個電子商務的系統(假設用C++實現),其中的模塊A需要發送大量的訂單信息給模塊B,通訊的方式使用socket。
假設訂單包括如下屬性:
--------------------------------
時間:time(用整數表示)
客戶id:userid(用整數表示)
交易金額:price(用浮點數表示)
交易的描述:desc(用字符串表示)
--------------------------------
如果使用protobuf實現,首先要寫一個proto文件(不妨叫Order.proto),在該文件中添加一個名爲"Order"的message結構,用來描述通訊協議中的結構化數據。該文件的內容大致如下:
--------------------------------
message Order
{
required int32 time = 1;
required int32 userid = 2;
required float price = 3;
optional string desc = 4;
}
--------------------------------
然後,使用protobuf內置的編譯器編譯 該proto。由於本例子的模塊是C++,你可以通過protobuf編譯器的命令行參數(看“這裏 ”),讓它生成C++語言的“訂單包裝類”。(一般來說,一個message結構會生成一個包裝類)
然後你使用類似下面的代碼來序列化/解析該訂單包裝類:
--------------------------------
// 發送方
Order order;
order.set_time(XXXX);
order.set_userid(123);
order.set_price(100.0f);
order.set_desc("a test order");
string sOrder;
order.SerailzeToString(&sOrder);
// 然後調用某種socket的通訊庫把序列化之後的字符串發送出去
// ......
--------------------------------
// 接收方
string sOrder;
// 先通過網絡通訊庫接收到數據,存放到某字符串sOrder
// ......
Order order;
if(order.ParseFromString(sOrder)) // 解析該字符串
{
cout << "userid:" << order.userid() << endl
<< "desc:" << order.desc() << endl;
}
else
{
cerr << "parse error!" << endl;
}
--------------------------------
有了這種代碼生成機制,開發人員再也不用吭哧吭哧地編寫那些協議解析的代碼了(幹這種活是典型的喫力不討好)。
萬一將來需求發生變更,要求給訂單再增加一個“狀態”的屬性,那隻需要在Order.proto文件中增加一行代碼。對於發送方(模塊A),只要增加一行設置狀態的代碼;對於接收方(模塊B)只要增加一行讀取狀態的代碼。哇塞,簡直太輕鬆了!
另外,如果通訊雙方使用不同的編程語言來實現,使用這種機制可以有效確保兩邊的模塊對於協議的處理是一致的。
順便跑題一下。
從某種意義上講,可以把proto文件看成是描述通訊協議的規格說明書(或者叫接口規範)。這種伎倆其實老早就有了,搞過微軟的COM編程或者接觸過CORBA的同學,應該都能從中看到IDL(詳細解釋看“這裏 ”)的影子。它們的思想是相通滴。