您的位置:首页 > 编程语言 > Go语言

Google Protobuf自动反射功能

2014-08-15 10:15 447 查看
Google Protobuf自动反射功能

    看了下Google Protobuf的源码,对于反射机制,无论c++实现还是java实现都是采用map查找,这个应很高效率。实际我们在项目中无形中也用 到了这种思路,仅仅没系统化。通过一个类的原型对象做辅助,然后配合map结构,就可很简单的根据符号名字来反射对象。从而实现一种抽象接口的稳定,把变
化隔离到了通讯协议 的数据内。
看一下从网络反射过程:
<span style="font-family:Microsoft YaHei;font-size:14px;">inline google::protobuf::Message* createMessage(const std::string& type_name)
{
google::protobuf::Message* message = NULL;
const google::protobuf::Descriptor* descriptor =
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name);
if (descriptor)
{
const google::protobuf::Message* prototype =
google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
if (prototype)
{
message = prototype->New();
}
}
return message;
}

//////////////以下是使用

buf[numbytes] = '\0'; //buf为从网络收到的数据
String data = buf;

//"gamesrv.RepLuaMsg"为 类名字
google::protobuf::Message* reply = createMessage("gamesrv.RepLuaMsg");

//gamesrv::RepLuaMsg p2;
reply->ParseFromString(data); //直接反序列化</span>

下面是一个采用反射实现的简单客户端:

// g++ -g `pkg-config --cflags protobuf` luaclient.cpp LuaCmd.pb.cc -o luacli `pkg-config --libs protobuf`
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string>
#include <iostream>
#include "LuaCmd.pb.h"
#include <google/protobuf/descriptor.h>

#include <google/protobuf/dynamic_message.h>

#define HOST "localhost"
#define PORT 8889
#define MAXDATASIZE 100

using namespace std;

inline google::protobuf::Message* createMessage(const std::string& type_name)
{
google::protobuf::Message* message = NULL;
const google::protobuf::Descriptor* descriptor =
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name);
if (descriptor)
{
const google::protobuf::Message* prototype =
google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
if (prototype)
{
message = prototype->New();
}
}
return message;
}

int main(int argc, char ** argv)
{
int fd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in server;

if (argc != 2) {
printf("Usage: %s \"COMMAND\"\n",argv[0]);
exit(0);
}

he = gethostbyname("10.57.220.70");
fd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr = *((struct in_addr *)he->h_addr);

int ret = connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr));

//for send
string data;
int cmdid = 1000;
char szTemp[1024]={'\0'};
gamesrv::LuaMsg p;
p.set_account("123");
p.set_msg("hideto.bj@gmail.com");
p.SerializeToString(&data);

*(int*)(szTemp+4) = htonl(cmdid);

int len = 4+4;
memmove(szTemp+8,data.c_str(),data.length());
len +=data.length();
*(int*)(szTemp) = htonl(len);
ret =send(fd, szTemp, len, 0);

memset(buf,0,sizeof(buf));
numbytes = recv(fd, buf, 8, 0);
numbytes = ntohl(*(int*)(buf))-8;
ret = recv(fd, buf, numbytes, 0);

buf[numbytes] = '\0';
data = buf;

google::protobuf::Message* reply = createMessage("gamesrv.RepLuaMsg");

reply->ParseFromString(data);
gamesrv::RepLuaMsg* rep = (gamesrv::RepLuaMsg*)reply;
cout << "People: " << endl;
cout << "ID: " << rep->account() << endl;
cout << "Email: " << rep->msg() << endl;
string mm = rep->msg();
close(fd);

return 0;
}

对应的proto文件LuaCmd.proto

package gamesrv;

option java_package = "gamesrv.Request.protocol";
option java_outer_classname = "LuaCmdProtos";

message LuaMsg {
required string account = 1; // Unique ID number for this person.
optional string msg = 2;
}

message RepLuaMsg {
required string account = 1; // Unique ID number for this person.
optional string msg = 2;
}


参考: http://blog.chinaunix.net/uid-52437-id-3143792.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: