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("[email protected]");
//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;
}