Protobuf 入门
原创
©著作权归作者所有:来自51CTO博客作者wx5fc8832a61484的原创作品,请联系作者获取转载授权,否则将追究法律责任
protocolbuffer是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
1. 下载
https://sourceforge.net/projects/protobuf/?source
protobuf-2.6.0.zip
https://github.com/google/protobuf
2. 编译
解压,打开protobuf.sln,编译生成库文件(libprotoc.lib,libprotobuf.lib)和编译器 (protoc.exe).
(只用生成libprotobuf,libprotoc,protoc三个项目即可)。
3. 编写proto通讯协议格式文件
用的是examples下的:addressbook.proto文件,如下:
// See README.txt for information and build instructions.
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}
- 命令生成(protoc.exe)
protoc -I=$$SRC_DIR –cpp_out=$DST_DIR addressbook.proto
SRC_DIR addressbook.proto目录,–cpp_out代表输出目录,addressBOOK.proto代表要编译的文件
我用的是:protoc -I=. –cpp_out=. addressbook.proto
(protoc.exe,addressbook.proto以及输出的addressbook.pb.h,addressbook.pb.cc都在当前目录下。) - 新建工程使用。
注意事项:
1).添加附加库目录(libprotoc.lib,libprotobuf.lib目录),并在程序中引用libprotoc.lib,libprotobuf.lib。
2).附加包含目录, protobuf-2.6.1\src。
3).addressbook.pb.cc 编译选项:不使用预编译头;
4).
错误 2 error C4996: ‘std::_Copy_impl’: Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning,
use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ ‘Checked Iterators’ c:\program files\microsoft visual studio 12.0\vc\include\xutility 2132 1 ProtobufDemo
添加预处理器定义:_SCL_SECURE_NO_WARNINGS 即可。
代码:
需要在VS中输入文件的命令行参数。
// ProtobufDemo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
// See README.txt for information and build instructions.
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
#pragma comment(lib, "libprotobuf.lib")
#pragma comment(lib, "libprotoc.lib")
using namespace std;
//#define WRITE_PROTOC
#ifdef WRITE_PROTOC
// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
int id;
cin >> id;
person->set_id(id);
cin.ignore(256, '\n');
cout << "Enter name: ";
getline(cin, *person->mutable_name());
cout << "Enter email address (blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
}
else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
}
else if (type == "work") {
phone_number->set_type(tutorial::Person::WORK);
}
else {
cout << "Unknown phone type. Using default." << endl;
}
}
}
// Main function: Reads the entire address book from a file,
// adds one person based on user input, then writes it back out to the same
// file.
int main(int argc, char* argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
return -1;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[1], ios::in | ios::binary);
if (!input) {
cout << argv[1] << ": File not found. Creating a new file." << endl;
}
else if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
// Add an address.
PromptForAddress(address_book.add_person());
{
// Write the new address book back to disk.
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
getchar();
return 0;
}
#else
// See README.txt for information and build instructions.
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {
for (int i = 0; i < address_book.person_size(); i++) {
const tutorial::Person& person = address_book.person(i);
cout << "Person ID: " << person.id() << endl;
cout << " Name: " << person.name() << endl;
if (person.has_email()) {
cout << " E-mail address: " << person.email() << endl;
}
for (int j = 0; j < person.phone_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phone(j);
switch (phone_number.type()) {
case tutorial::Person::MOBILE:
cout << " Mobile phone #: ";
break;
case tutorial::Person::HOME:
cout << " Home phone #: ";
break;
case tutorial::Person::WORK:
cout << " Work phone #: ";
break;
}
cout << phone_number.number() << endl;
}
}
}
// Main function: Reads the entire address book from a file and prints all
// the information inside.
int main(int argc, char* argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
return -1;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[1], ios::in | ios::binary);
if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
ListPeople(address_book);
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
getchar();
return 0;
}
#endif
输入(#define WRITE_PROTOC):

输出(注释#define WRITE_PROTOC):

socket通讯传输:
namespaceT::ClassA p;
p.set_id(1);
string data;
p.SerizlizeToString(&data);
char dat[255];
strcpy(dat,data.c_str());
send(socket,dat,data.length(),0);
char recvMsg[1000];
namespaceT::ClassA p;
recv(socket,recvMsg,100,0);
string data = recvMsg;
p.ParseFromString(data);
cout<<p.id()<<endl;