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;
}