21xrx.com
2024-11-25 05:08:06 Monday
登录
文章检索 我的文章 写文章
Protobuf C++ Socket 示例
2023-06-24 19:27:45 深夜i     --     --
Protobuf C++ Socket 示例 数据交换

Protobuf(Protocol Buffers)是Google开发的一种数据序列化协议,使用它可以将结构化数据转换为二进制数据格式,以便在不同的软件系统间进行数据交换。在计算机科学领域,数据序列化是非常重要的。使用Protobuf能够简化网络通信,提高程序性能,节省带宽。本文将介绍Protobuf在C++ Socket示例中的应用。

首先,我们需要创建一个简单的Protobuf消息。以下是一个示例:


syntax = "proto3";

package protobufexample;

message Person

  string name = 1;

  int32 age = 2;

  string address = 3;

上述代码定义了一个Person消息,包含三个字段:name、age和address。

接下来,我们需要生成C++代码。我们可以使用Protobuf的编译器protoc来生成代码。以下是生成代码的命令:


$ protoc --cpp_out=. person.proto

这个命令将会在当前目录下生成名为person.pb.cc和person.pb.h的C++代码文件。

通过这些生成的代码,我们可以开始构建一个TCP服务器和客户端,以进行与Person消息的交互。

下面的代码是一个基于Socket的Protobuf服务器示例代码。它侦听来自客户端的请求,将Person消息解析为一个流并将其打印到控制台上:


#include <iostream>

#include <memory>

#include <stdexcept>

#include <string>

#include <sys/socket.h>

#include <netinet/in.h>

#include <unistd.h>

#include <google/protobuf/io/coded_stream.h>

#include <google/protobuf/io/zero_copy_stream_impl.h>

#include "person.pb.h"

using namespace std;

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

  int server_fd, new_socket;

  struct sockaddr_in address;

  int opt = 1;

  int addrlen = sizeof(address);

  char buffer[1024] = {0};

   

  // 创建Socket

  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {

    perror("socket failed");

    exit(EXIT_FAILURE);

  }

   

  // 设置Socket选项

  if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {

    perror("setsockopt");

    exit(EXIT_FAILURE);

  }

  address.sin_family = AF_INET;

  address.sin_addr.s_addr = INADDR_ANY;

  address.sin_port = htons(8080);

   

  // 绑定Socket

  if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {

    perror("bind failed");

    exit(EXIT_FAILURE);

  }

  

  // 监听Socket

  if (listen(server_fd, 3) < 0) {

    perror("listen");

    exit(EXIT_FAILURE);

  }

  

  // 接受数据

  while ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))) {

    int n = read(new_socket, buffer, 1024);

    

    // 解析并打印Person消息

    protobufexample::Person person;

    google::protobuf::io::ArrayInputStream ais(buffer, n);

    google::protobuf::io::CodedInputStream coded_input(&ais);

    coded_input.ReadMessage(&person);

    cout << "Name: " << person.name() << endl;

    cout << "Age: " << person.age() << endl;

    cout << "Address: " << person.address() << endl;

  }

  return 0;

}

以下是一个基于Socket的Protobuf客户端示例代码。它将发送一个Person消息到服务器:


#include <iostream>

#include <memory>

#include <stdexcept>

#include <string>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <google/protobuf/io/coded_stream.h>

#include <google/protobuf/io/zero_copy_stream_impl.h>

#include "person.pb.h"

using namespace std;

   

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

  int sock = 0, valread;

  struct sockaddr_in serv_addr;

  char buffer[1024] = {0};

   

  // 创建Socket

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

    cout << "\n Socket creation error \n" << endl;

    return -1;

  }

 

  serv_addr.sin_family = AF_INET;

  serv_addr.sin_port = htons(8080);

   

  // 转换IP地址

  if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {

    cout << "\nInvalid address/ Address not supported \n" << endl;

    return -1;

  }

 

  // 连接Socket

  if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {

    cout << "\nConnection Failed \n" << endl;

    return -1;

  }

  

  // 构建并发送Person消息

  protobufexample::Person person;

  person.set_name("John");

  person.set_age(30);

  person.set_address("1234 Main St, Vancouver, BC");

  

  google::protobuf::io::StringOutputStream raw_output(buffer);

  google::protobuf::io::CodedOutputStream coded_output(&raw_output);

  coded_output.WriteVarint32(person.ByteSize());

  person.SerializeToCodedStream(&coded_output);

  send(sock , buffer , coded_output.ByteCount(), 0 );

  cout << "Person message sent" << endl;

  return 0;

}

以上是一个基于Socket的Protobuf服务器和客户端示例。我们使用Protobuf来传递结构化数据,并在服务器和客户端之间进行通信。在实际开发中,使用Protobuf可以使网络通信更加快速和高效。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复