Protocol Buffer在C++网络编程中使用教程

来源:互联网 发布:捷联惯导速度算法 编辑:程序博客网 时间:2024/06/18 15:10

1. 下载 Protocol Buffers v2.6.1

https://github.com/google/protobuf/releases/tag/v2.6.1

2.使用 vs2012 编译 protobuf-2.6.1\vsprojects\protobuf.sln

在解决方案中 逐项进行编译,在Debug目录中生成lib和exe,
文件生成清单如下:
libprotobuf.lib
libprotobuf-lite.lib
libprotoc.lib 

lite-test.exe
protoc.exe
test_plugin.exe
tests.exe

3. protobuf测试:

创建两个工程(),每个工程都要添加 protobuf头文件 和 lib文件。

(1). 在属性-> C/C++ ->常规 (附加包含目录)
     添加 C:\xiaofan\tools\protobuf\protobuf-2.6.1\src

(2). 在属性-> 链接器 ->常规 (附加库目录)
     添加 C:\xiaofan\tools\protobuf\protobuf-2.6.1\libs 
     (注意: 此处的 libs 是我自己创建的,把Debug中的 lib 拷贝了进去 )

4.创建people.proto:

package PeopleT.Test;     message People  {       required string name = 1;       required int32 id = 2;       required string email = 3;     };

编译生成头文件:
找到protoc.exe,运行cmd :
protoc -I=. --cpp_out=. people.proto
生成 people.pb.h 和 people.pb.cc

5.程序调用

使用VS2012分别创建protobuf_client和protobuf_server 程序。
把people.pb.h 和 people.pb.cc加入程序,在主程序中使用命名空间,

#include "people.pb.h"using namespace PeopleT::Test;

注意:

(1).在windows下写socket程序时,需要加入 #pragma comment( lib, "ws2_32.lib")  ,该库主要提供网络相关API的支持。

(2).编译过程中如果遇到问题,请参见之前的文章:

在VS2012中 集成protobuf 文件时, 编译出现问题

详情参见程序如下:

// 客户端程序#include "stdafx.h"#include <stdio.h>#include <WinSock2.h>  #include <iostream>#include <string>#include <ctime>#include "people.pb.h"using namespace std;using namespace PeopleT::Test;#pragma comment( lib, "ws2_32.lib")const int BUFFSIZE = 128;int _tmain(int argc, _TCHAR* argv[]){WSADATA     wsd;               //WSADATA变量  SOCKET socketfd;               //服务器套接字  struct sockaddr_in seraddr ;   //服务器地址  string hostip = "127.0.0.1"; //初始化套结字动态库  if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)  {cout << "WSAStartup failed!" << endl;  return -1;  }IPPROTO_TCP;//链接,尝试3次for(int i = 0 ; i < 3;++i){if((socketfd = socket(AF_INET,SOCK_STREAM,0)) > 0){cout<<"create socket success..."<<endl;break;}Sleep(2000);}if(INVALID_SOCKET == socketfd){cout<<"socket failed"<<endl;WSACleanup();//释放套接字资源  return -1;}//地址置空memset( &seraddr, sizeof(seraddr) ,0);//设置服务器地址  seraddr.sin_family = AF_INET ;seraddr.sin_port = htons(9999);seraddr.sin_addr.s_addr = inet_addr(hostip.c_str());//尝试连接到服务端地址if(connect(socketfd,(struct sockaddr *)&seraddr, sizeof(seraddr)) < 0){cout<<"connect to server failed ..."<<endl;closesocket(socketfd);WSACleanup();       //释放套接字资源  return -1;}People myprotobuf;char buff[BUFFSIZE];while( true ){int curtime = time(NULL) ;//以下方法的实现可以Test.pb.h中找到myprotobuf.set_name("wang");myprotobuf.set_id(2);myprotobuf.set_email("abc@123.com");//protobuf的序列化方式之一memset(buff,0,BUFFSIZE);myprotobuf.SerializeToArray(buff,BUFFSIZE);if(send(socketfd,buff,strlen(buff),0) < 0){cout<<curtime<<": send failed ..."<<endl;break;}cout<<curtime<<": send success ..."<<endl;Sleep(3000);    //每隔3s发送一次}closesocket(socketfd);WSACleanup();       //释放套接字资源  return 0;}

// 服务端程序#pragma #include "stdafx.h"#include <winsock2.h>#include <stdio.h>#include <cstdio>  #include <iostream>#include <string>#include <ctime>#include "people.pb.h"#pragma comment( lib, "ws2_32.lib")using namespace std;using namespace PeopleT::Test;const int BUFFSIZE = 128;const int QLEN = 10 ;int _tmain(int argc, char* argv[]){WSADATA         wsd;            //WSADATA变量  SOCKET     listenfd;            //服务器套接字 int          connfd;            //客户端套接字  struct sockaddr_in seraddr ;    //服务器地址//初始化套结字动态库  if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)  {cout << "WSAStartup failed!" << endl;  return -1;  }//建立socket//AF_INET:IPv4因特网域//SOCK_STREAM:TCP链接//0:给定前两个参数,选择默认的协议listenfd = socket(AF_INET,SOCK_STREAM,0);if(listenfd < 0 ){cout<<"socket failed"<<endl;WSACleanup();//释放套接字资源;  return -1;}//地址置空memset(&seraddr,sizeof(seraddr),0);//服务器套接字地址   seraddr.sin_family = AF_INET ;seraddr.sin_port = htons(9999);seraddr.sin_addr.s_addr = htonl(INADDR_ANY);//关联地址和套接字if(bind(listenfd,(struct sockaddr *)&seraddr, sizeof(seraddr)) < 0){cout<<"bind address with socket failed..."<<endl;closesocket(listenfd);WSACleanup();  //释放套接字资源;  return -1;}//调用listen,宣告server愿意接受链接请求 : 开始监听if(listen(listenfd,QLEN) == INVALID_SOCKET   ){cout<<"listen on socket failed..."<<endl;closesocket(listenfd);WSACleanup();  //释放套接字资源return -1;}//获得连接请求,并建立连接if( (connfd = accept(listenfd,(struct sockaddr *)NULL,NULL)) < 0 ){cout<<"accept the request failed"<<endl;closesocket(listenfd);WSACleanup();  //释放套接字资源return -1;}People  myprotobuf;char buff[BUFFSIZE];while( true ){if(recv(connfd,buff,sizeof(buff),0) < 0){cout<<"recv failed ..."<<endl;break;}//protobuf反序列化myprotobuf.ParseFromArray(buff,BUFFSIZE);cout<<"name :"<<myprotobuf.name()<<"\n"<<"id :"<<myprotobuf.id()<<"\n"<<"email :"<<myprotobuf.email()<<endl;memset(buff,0,BUFFSIZE);}closesocket(listenfd);closesocket(connfd);WSACleanup();  //释放套接字资源return 0;}
0 0
原创粉丝点击