Ubuntu16.04安装使用protobuf2(一)

简介

	本人也是protobuf新手,因项目需要才接触到的。开始按照官方教程整了一整天最新版的proto3,死活配置
不成功。所以直接使用了proto2。

安装

ubuntu16,04默认是带有proto2的。

通过protoc --version 可查看安装的版本。

zxp@zxp-pc:~/zxp/proto_test$ protoc --version
libprotoc 2.6.1
zxp@zxp-pc:~/zxp/proto_test$

如果提示未安装,安装即可。

sudo apt install protobuf-compiler

第一个simple

这部分代码我是参考这个博主的文章:点此跳转

使用protobuf首先我们需要定义自己的.proto文件,这个文件主要是消息类型的定义。

Ubuntu16.04安装使用protobuf2(一)_第1张图片
simple
addressbook.proto

package tutorial;  
message Person {
  required string name = 1;
  required int32 id = 2;
  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; 
}  

message AddressBook {
  repeated Person person = 1; 
}

调用protoc工具转换成接口文件。

protoc -I=./  --cpp_out=./ ./addressbook.proto

执行成功会生成一下俩文件:

addressbook.pb.cc
addressbook.pb.h

这俩文件就是接口文件,当做普通的.cpp和.h使用即可。

写入

#include 
#include 
#include 
#include "addressbook.pb.h"
using namespace std;

// 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();

  return 0;
}

读出

#include 
#include 
#include 
#include "addressbook.pb.h"
using namespace std;

// 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();

  return 0;
}

我是使用Cmake来构建项目的。
CMakeLists.txt

我这里test1.cpp是写 test2.cpp是读

cmake_minimum_required(VERSION 3.5)

set(CMAKE_CXX_STANDARD 14)
project(write)

include_directories(
    ./include/
)

add_executable(write test1.cpp addressbook.pb.cc addressbook.pb.h )

target_link_libraries(write PRIVATE
    protobuf
    pthread
)

写的比较简陋~~~各位看官凑合凑合

编译三部曲

zxp@zxp-pc:~/zxp/proto_test$ mkdir build && cd build
zxp@zxp-pc:~/zxp/proto_test/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zxp/zxp/proto_test/build
zxp@zxp-pc:~/zxp/proto_test/build$ make
[ 33%] Building CXX object CMakeFiles/write.dir/test1.cpp.o
[ 66%] Building CXX object CMakeFiles/write.dir/addressbook.pb.cc.o
[100%] Linking CXX executable write
[100%] Built target write
zxp@zxp-pc:~/zxp/proto_test/build$

编译读的,改改cmake即可。
运行
写:

zxp@zxp-pc:~/zxp/proto_test/build$ ./write file
file: File not found.  Creating a new file.
Enter person ID number: 666
Enter name: 6666666
Enter email address (blank for none): 6666@6666
Enter a phone number (or leave blank to finish): 
zxp@zxp-pc:~/zxp/proto_test/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  file  Makefile  write

读:

zxp@zxp-pc:~/zxp/proto_test/build$ ./read file 
Person ID: 666
  Name: 6666666
  E-mail address: 6666@6666
zxp@zxp-pc:~/zxp/proto_test/build$

项目实际使用方式

send:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "addressbook.pb.h"
using namespace std;

#define IP "127.0.0.1"

// 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;
    }
  }
}

int main(int argc, char *argv[])
{
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock == -1)
  {
    cerr << "Error creating socket." << endl;
    return 1;
  }
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(IP);
  addr.sin_port = 13159;
  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  {
    cerr << "Error binding socket." << endl;
    return 1;
  }

  tutorial::AddressBook address_book;

  // Add an address.
  PromptForAddress(address_book.add_person());

  {
    std::string message;
    address_book.SerializeToString(&message);
    struct sockaddr_in addrs;
    addrs.sin_family = AF_INET;
    addrs.sin_addr.s_addr = inet_addr(IP);
    addrs.sin_port = 13157;
    sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&addrs, sizeof(sockaddr_in));
  }
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

recv:

#include 
#include 
#include 

#include 
#include 
#include 
#include 

#include "addressbook.pb.h"
using namespace std;

// 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;

  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock == -1)
  {
    cerr << "Error creating socket." << endl;
    return 1;
  }
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = INADDR_ANY;
  addr.sin_port = 13157;
  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  {
    cerr << "Error binding socket." << endl;
    return 1;
  }
  char buf[2048] = {0};
  int len = strlen(buf);
std:
  cout << "wait connect ..." << std::endl;
  recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, (socklen_t *)&len);
  std::cout << "connect successfull ..." << std::endl;
  tutorial::AddressBook address_book;

  {
    if (!address_book.ParseFromString(buf))
    {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  ListPeople(address_book);

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

运行:

zxp@zxp-pc:~/zxp/proto_test/build$ ./write 
Enter person ID number: 999
Enter name: 999
Enter email address (blank for none): 999
Enter a phone number (or leave blank to finish): 
zxp@zxp-pc:~/zxp/proto_test/build$ 
zxp@zxp-pc:~/zxp/proto_test/build$ ./read 
wait connect ...
connect successfull ...
Person ID: 999
  Name: 999
  E-mail address: 999
zxp@zxp-pc:~/zxp/proto_test/build$

你可能感兴趣的:(protobuf,1024程序员节)