protobuf和socket通信简单实例

  protobuf是 Google 公司内部的混合语言数据标准,可以用来定义通信的协议,由于其有序列化和反序列化的操作,减小了存储或通信的数据量,从而达到高效运行的目的。
  此实例在ubuntu18.04下正常运行,其它操作系统没有经过测试,无法保证正常运行。

protobuf安装

  protobuf的下载地址,如图1所示的安装包,安装可参考官网官网安装说明。

图1

  下载完毕解压后,在主文件夹下运行以下命令进行安装。

 ./configure
make
make check
sudo make install
sudo ldconfig # refresh shared library cache.

编辑程序及编译

  本文参考protobuf官网的教程,使用C++编写socket的服务端,python编写socket的客户端,最终实现服务端接收来自客户端的protobuf数据流。总共有4个文件(addressbook.proto、server.cpp、client.py、CMakeLists.txt)需要编写,其它文件通过命令自动生成,步骤如下:

  1. 创建工作空间文件夹protobuf_socket,并在protobuf_socket下创建必要的文件。
mkdir protobuf_socket
touch addressbook.proto
touch server.cpp
touch client.py
touch CMakeLists.txt

  生成的文件目录如图2所示。

图2
  1. 在addressbook.proto文件中添加如下内容:
syntax = "proto2";package tutorial;message Person {optional string name = 1;optional int32 id = 2;optional string email = 3;enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2;}message PhoneNumber {optional string number = 1;optional PhoneType type = 2 [default = MOBILE];}repeated PhoneNumber phones = 4;
}message AddressBook {repeated Person people = 1;
}
  1. 在server.cpp文件中添加如下内容:
#include <iostream>
#include <fstream>
#include <string>
#include <boost/asio.hpp>#include "addressbook.pb.h"using namespace boost::asio;
using namespace std;#define MAX_SIZE 128 * 1024// 打印输出
void ListPeople(const tutorial::AddressBook& address_book) {for (int i = 0; i < address_book.people_size(); i++) {const tutorial::Person& person = address_book.people(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.phones_size(); j++) {const tutorial::Person::PhoneNumber& phone_number = person.phones(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;}}
}int main(int argc, char* argv[]) {// 验证库的版本与头文件编译的内容是否一致GOOGLE_PROTOBUF_VERIFY_VERSION;// 所有asio类都需要io_service对象io_service iosev;ip::tcp::acceptor acceptor(iosev, ip::tcp::endpoint(ip::tcp::v4(), 5000));while(1) {// socket对象ip::tcp::socket socket(iosev);// 等待直到客户端连接进来acceptor.accept(socket);// 显示连接进来的客户端std::cout << socket.remote_endpoint().address() << std::endl;boost::system::error_code ec;// 接收数据char buf[MAX_SIZE];size_t len = socket.read_some(buffer(buf), ec);if(len >= MAX_SIZE) {std::cout << "data is too big, receive failed!" << std::endl;continue;}// 如果出错,打印出错信息if(ec) {std::cout << "receive error: " << boost::system::system_error(ec).what() << std::endl;continue;}tutorial::AddressBook address_book;if(address_book.ParseFromArray(buf, len) != 1) {    //序列化std::cout << "Failed to parse address book." << std::endl;}ListPeople(address_book);}// 可选项:删除所有protobuf分配的全局对象google::protobuf::ShutdownProtobufLibrary();return 0;
}
  1. 在client.py文件下添加如下内容:
#! /usr/bin/python
#  coding=utf-8import socket
import addressbook_pb2
import sysMAX_SIZE = 128 * 1024#创建socket通信的对象
client = socket.socket()#连接服务器的IP地址和端口号
client.connect(("localhost", 5000))# 手动输入消息并打印
def PromptForAddress(person):person.id = int(input("Enter person ID number: "))person.name = input("Enter name: ")email = input("Enter email address (blank for none): ")if email != "":person.email = emailwhile True:number = input("Enter a phone number (or leave blank to finish): ")if number == "":breakphone_number = person.phones.add()phone_number.number = numbertype = input("Is this a mobile, home, or work phone? ")if type == "mobile":phone_number.type = addressbook_pb2.Person.PhoneType.MOBILEelif type == "home":phone_number.type = addressbook_pb2.Person.PhoneType.HOMEelif type == "work":phone_number.type = addressbook_pb2.Person.PhoneType.WORKelse:print ("Unknown phone type; leaving as default value.")if __name__ == "__main__":address_book = addressbook_pb2.AddressBook()PromptForAddress(address_book.people.add())msg = address_book.SerializeToString()if len(msg) >= MAX_SIZE:print('data is too big, server will not receive data!')client.send(msg)
  1. 在CMakeLists.txt文件下添加如下内容:
# Minimum CMake required
cmake_minimum_required(VERSION 3.1.3)if(protobuf_VERBOSE)message(STATUS "Protocol Buffers Configuring...")
endif()# CMake policies
cmake_policy(SET CMP0022 NEW)
# On MacOS use @rpath/ for target's install name prefix path
if (POLICY CMP0042)cmake_policy(SET CMP0042 NEW)
endif ()
# Clear VERSION variables when no VERSION is given to project()
if(POLICY CMP0048)cmake_policy(SET CMP0048 NEW)
endif()# Project
project(protobuf_test C CXX)find_package(Boost COMPONENTS regex system REQUIRED)# Add c++11 flags
if (CYGWIN)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
else()set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED ON)set(CMAKE_CXX_EXTENSIONS OFF)
endif()add_executable(server server.cpp addressbook.pb.cc)
target_link_libraries(server protobuf ${Boost_LIBRARIES})
  1. 在protobuf_socket文件夹下编译addressbook.proto文件
protoc -I=. --cpp_out=. addressbook.proto
protoc -I=. --python_out=. addressbook.proto

 &ems; “-I=.”表示编译的文件(addressbook.proto)位于当前文件夹。“-cpp_out=.”表示将生成的文件放在当前文件夹。最终生成的文件目录如图3所示。

图3
  1. 在protobuf_socket文件夹下编译客户端server.cpp文件
mkdir build
cd build
cmake ..
make

运行程序

  1. 在protobuf_socket文件夹下运行服务端程序
./build/server
  1. 在protobuf_socket文件夹下运行客户端程序,并根据提示输入信息,在服务端将看到最终的信息。
python3 client.py

protobuf和socket通信简单实例相关推荐

  1. linux下TCP通信简单实例

    linux下TCP通信简单实例 基于TCP(面向连接)的socket编程,分为服务器端和客户端 服务器端的流程如下: (1)创建套接字(socket) (2)将套接字绑定到一个本地地址和端口上(bin ...

  2. 如何在Windows环境下的VS中安装使用Google Protobuf完成SOCKET通信

    http://blog.csdn.net/whuancai/article/details/11994341 如何在Windows环境下的VS中安装使用Google Protobuf完成SOCKET通 ...

  3. flash php socket通信_php socket通信机制实例说明

    php socket通信机制实例说明与代码----什么是socket 所谓socket一般也称作"套接字",用于描述ip地址和端口,是一个通讯链的句柄.使用程序一般经过" ...

  4. Android中socket通信简单实现

    Android中socket通信简单实现 socket通信需要有一个服务器和客户端,可以把同一个APP作为服务器跟客户端,也可以分开成两个APP. 先上个图: 这里以一个APP作为服务器跟客户端为示例 ...

  5. python socket编程之双方相互通信简单实例_扣丁学堂Python开发socket实现简单通信功能实例...

    扣丁学堂Python开发socket实现简单通信功能实例 2018-08-21 14:12:38 747浏览 今天扣丁学堂Python培训老师给大家结合实例介绍一下关于socket实现的简单通信功能, ...

  6. python socket编程之双方相互通信简单实例_Python socket实现的简单通信功能示例

    套接字(socket)是计算机网络数据结构,在任何类型的通信开始之前,网络应用程序必须创建套接字,可以将其比作电话的插孔,没有它将无法进行通信 常用的地址家族 AF_UNIX:基于文件,实现同一主机不 ...

  7. C#中Socket通信用法实例详解

    本文实例讲述了C#中Socket通信用法.分享给大家供大家参考.具体如下: 一.UDP方式: 服务器端代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 ...

  8. Android Socket通信简单使用

    公司要实现一个简单的聊天功能,提前研究一下 Socket 通信,而公司的服务端功能又没有实现,所以这里就把服务端的功能放到一个界面实现了. 一.原生 Socket 通信 1.Activity 布局 简 ...

  9. python socket编程之双方相互通信简单实例

    实例说明: 本实例实现真实局域网内两个物理主机的相互通信,两个物理主机的操作系统分别是windows8.1和windows10. 实例代码: 客户端 import socket addr = ('21 ...

最新文章

  1. solr 自定义 dismax查询方式
  2. idea的总部_Studio Didea新总部办公室,意大利 / Studio Didea
  3. Javascript获取For循环所用时间
  4. [转载] 基本概念:java中的访问修饰符
  5. TOMCAT 优化设置
  6. arcgis中给属性文件加x y坐标
  7. Impala和Inceptor的区别
  8. 『中安网培』***游戏过关攻略
  9. 计算机工作表中按升序排列,表格打乱顺序怎么按顺序排列_怎么把表格内容按顺序排列图文步骤...
  10. Win10永久禁用键盘上的num lock键,解决打字时经常误触的困扰
  11. tensorrt expecting compute 7.5 got compute 6.1, please rebuild
  12. python的撤销和回退_撤销和回退
  13. 历经一个月研究,发布两款机器人,小白就会python自己制作机器人了
  14. 2023测绘资质申请条件
  15. 数据恢复软件如何恢复电脑删除的文件
  16. Spring Cloud Alibaba
  17. JS - 函数柯里化
  18. ioa的app开发和android区别,ioA 7000
  19. ECM:发动机和燃烧系统测试设备
  20. MIUI国际/欧版使用小米应用商店/国内浏览器-解决不会下载软件/上网问题

热门文章

  1. android route命令详解,route cmd命令详解
  2. python中的点表示什么_Python里面这些点,新手看完之后完全不知道这些点
  3. 图像点云数据融合方法汇总
  4. 谷歌最新开源BundleTrack: 无需任何CAD模型的6D物体姿态跟踪算法
  5. StereoDRNet:基于stereo的三维重建网络
  6. 事件相机角点检测,从原理到demo
  7. 英伟达人工智能和处理器驱动的制药、生命科学合作
  8. Linux 下的动态库、静态库与环境变量
  9. 美国微生物科学院22年院士公布!舒跃龙、黄力、卢洪洲、赵国屏!
  10. 科研人专属微信红包封面免费送!速领