21xrx.com
2025-03-28 02:39:48 Friday
文章检索 我的文章 写文章
Protobuf C++ Socket 示例
2023-07-09 18:42:59 深夜i     15     0
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可以使网络通信更加快速和高效。

  
  

评论区

请求出错了