在c++中使用protubuf3,socket的demo

本文档提供了一篇关于如何在C++环境中使用protobuf3进行socket通信的教程,包括msg.proto文件的创建,编译生成msg.pb.h和msg.pb.cc,以及在server.cpp和client.cpp中应用ParseFromString和SerializeToString接口。通过makefile进行编译,并介绍了使用C接口的可能性。

安装
https://www.jianshu.com/p/ea1cdd33f2b3

也可

sudo apt-get install protobuf-c-compiler protobuf-compiler
protoc --version

msg.proto

syntax = "proto3";
package tutorial;
message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;
}

编译

/usr/local/bin/protoc  -I=./   --cpp_out=./   msg.proto 

生成
msg.pb.h,msg.pb.cc

server.cpp
使用 ParseFromString 接口

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<string>
#include<iostream>

#include"msg.pb.h"
using namespace std;
#define SIZE 300

int main(int argc,char *argv[])
{
        int server_sock,client_sock,r;
        struct sockaddr_in server_addr,client_addr;
        socklen_t len;
        char buf[SIZE];
        if(argc!=2)
        {
                printf("need port\n");
                return 1;
        }
        int port = atoi(argv[1]);
        server_sock = socket(AF_INET,SOCK_STREAM,0);
        memset(&server_addr,0,sizeof server_addr);
        server_addr.sin_family=AF_INET;
        server_addr.sin_addr.s_addr=inet_addr("0.0.0.0");//htonl(INADDR_ANY)
        server_addr.sin_port=htons(port);
        if(-1 == bind(server_sock, (struct sockaddr*)&server_addr,sizeof(server_addr)))
        {
                printf(" bind error\n");
                return -1;
        }
        if(-1 == listen(server_sock, 10))
        {
                printf(" listen error\n");
                return -1;
        }
        printf("listen on %d\n",port);

        client_sock=accept(server_sock,(struct sockaddr*)&client_addr,&len);

        //string s;

        memset(buf,0,SIZE);
        /*
        while( r=read(client_sock,buf,10)> 0 ) {
                buf[r]='\0';
                s+=buf;
                memset(buf,0,SIZE);
        }*/
        r=read(client_sock,buf,SIZE);
        buf[r]='\0';
        string s=buf;
        printf("read r=%d, s.length()=%ld\n",r,s.length());
        //解析客户端发来的数据
        tutorial::Person people;
        people.ParseFromString(s);
        cout<<people.name()<<" "<<people.id()<<" "<<people.email()<<endl; 

                close(client_sock);
                close(server_sock);
        return 0;
}

client.cpp
使用 SerializeToString

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<iostream>

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


int main(int argc,char*argv[])
{
        if(argc!=3)
        {
                printf("ip + port\n");
                return 1;
        }
        int sock;
        struct sockaddr_in addr;
        memset(&addr,0,sizeof(addr));
        socklen_t len;
        sock=socket(AF_INET,SOCK_STREAM,0);
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr=inet_addr(argv[1]);
        addr.sin_port=htons(atoi(argv[2]));
        len=sizeof addr;
        int r=connect(sock,(struct sockaddr*)&addr,len);
        if(r==-1)
        {
                printf("connect error\n");
                return 0;
        }

        tutorial::Person p;
        p.set_name("李四");
        p.set_id(1);
        p.set_email("36985695@qq.com");
    
        string buf;
        p.SerializeToString(&buf);

        r=write(sock,buf.c_str(),buf.length());
                if (r != buf.length())
                {
                        printf("send error\n");
                        exit(1);
                }
        printf("write r=%d, buf.length()=%ld\n",r,buf.length());
        close(sock);
        return 0;
}

makefile

INC=/usr/local/include/google/protobuf
LIB=/usr/local/lib
lib=protobuf

all:server client
server:server.cpp msg.pb.cc
        g++ -g -o $@ $^ -I$(INC) -L$(LIB) -l$(lib)
client:client.cpp msg.pb.cc
        g++ -g -o $@ $^ -I$(INC) -L$(LIB) -l$(lib)
clean:
        rm -rf server client

编译:

gdut17@ubuntu:~/protobuf_new_test$ make clean
rm -rf server client
gdut17@ubuntu:~/protobuf_new_test$ make
g++ -g -o server server.cpp msg.pb.cc -I/usr/local/include/google/protobuf -L/usr/local/lib -lprotobuf
g++ -g -o client client.cpp msg.pb.cc -I/usr/local/include/google/protobuf -L/usr/local/lib -lprotobuf
gdut17@ubuntu:~/protobuf_new_test$ ./server 8888
listen on 8888
read r=27, s.length()=27
李四 1 36985695@qq.com
gdut17@ubuntu:~/protobuf_new_test$ ./client 127.0.0.1 8888
write r=27, buf.length()=27

使用C接口也行

gdut17@ubuntu:~/protobuf_new_test$ cat c_test.c 
#include "msg.pb.h"

#include<arpa/inet.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

/*
//C数组的序列化和序列化API
//在/usr/local/include/google/目录下,查找包含"SerializeToArray"所有的文件,同时打印所在行
//sudo grep "SerializeToArray" -r /usr/local/include/google/ -n

bool SerializeToArray(void* data, int size) const; //序列化
bool ParseFromArray(const void* data, int size);   //反序列化
*/
char buf[1024];
size_t len;

void set_person()
{
    tutorial::Person obj;
    obj.set_name("mike");
    obj.set_id(1);
    *obj.mutable_email() = "xxx@qq.com"; //obj.set_email("xxx@qq.com");
    len = obj.ByteSizeLong();
  //  len = obj.ByteSize(); //获取长度
    //cout << "len = " << len << endl;
        printf("len=%ld\n",len);

    obj.SerializeToArray(buf, len);//序列化,obj成员保存在buf中
}

void get_person()
{
    tutorial::Person obj;
    obj.ParseFromArray(buf, len); //反序列化,buf的内容设置给obj的成员
    
   printf("%s %d %s\n",obj.name().c_str(),obj.id(),obj.email().c_str());


    cout<<obj.name()<<" "<<obj.id()<<" "<<obj.email()<<endl;
}

int main()
{

    set_person(); //序列化
    get_person(); //反序列化

    return 0;
}
/*
g++ -g -o c_test c_test.c msg.pb.cc -I/usr/local/include/google/protobuf -L/usr/local/lib -lprotobuf

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值