Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7278492
  • 博文数量: 512
  • 博客积分: 12019
  • 博客等级: 上将
  • 技术积分: 6857
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-01 16:46
文章分类

全部博文(512)

文章存档

2024年(2)

2022年(2)

2021年(6)

2020年(59)

2019年(4)

2018年(10)

2017年(5)

2016年(2)

2015年(4)

2014年(4)

2013年(16)

2012年(47)

2011年(65)

2010年(46)

2009年(34)

2008年(52)

2007年(52)

2006年(80)

2005年(22)

分类: C/C++

2012-03-22 13:57:34

看了下Google Protobuf的源码,对于反射机制,无论c++实现还是java实现都是采用map查找,这个应很高效率。实际我们在项目中无形中也用 到了这种思路,仅仅没系统化。通过一个类的原型对象做辅助,然后配合map结构,就可很简单的根据符号名字来反射对象。从而实现一种抽象接口的稳定,把变 化隔离到了通讯协议 的数据内。

可参考http://blog.chinaunix.net/uid-52437-id-3142718.html文章。

原型 prototype pattern参考http://blog.chinaunix.net/uid-52437-id-2108601.html

wiki: 

看一下从网络反射过程:

点击(此处)折叠或打开

  1. inline google::protobuf::Message* createMessage(const std::string& type_name)
  2. {
  3.   google::protobuf::Message* message = NULL;
  4.   const google::protobuf::Descriptor* descriptor =
  5.     google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name);
  6.   if (descriptor)
  7.   {
  8.     const google::protobuf::Message* prototype =
  9.       google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
  10.     if (prototype)
  11.     {
  12.       message = prototype->New();
  13.     }
  14.   }
  15.   return message;
  16. }

  17. //////////////以下是使用

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

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

  22. //gamesrv::RepLuaMsg p2;
  23. reply->ParseFromString(data); //直接反序列化

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

点击(此处)折叠或打开

  1. // g++ -g `pkg-config --cflags protobuf` luaclient.cpp LuaCmd.pb.cc -o luacli `pkg-config --libs protobuf`
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <strings.h>
  5. #include <stdlib.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <netdb.h>
  10. #include <string>
  11. #include <iostream>
  12. #include "LuaCmd.pb.h"
  13. #include <google/protobuf/descriptor.h>
  14.                           
  15. #include <google/protobuf/dynamic_message.h>

  16. #define HOST "localhost"
  17. #define PORT 8889
  18. #define MAXDATASIZE 100

  19. using namespace std;


  20. inline google::protobuf::Message* createMessage(const std::string& type_name)
  21. {
  22.   google::protobuf::Message* message = NULL;
  23.   const google::protobuf::Descriptor* descriptor =
  24.     google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name);
  25.   if (descriptor)
  26.   {
  27.     const google::protobuf::Message* prototype =
  28.       google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
  29.     if (prototype)
  30.     {
  31.       message = prototype->New();
  32.     }
  33.   }
  34.   return message;
  35. }


  36. int main(int argc, char ** argv)
  37. {
  38.   int fd, numbytes;
  39.   char buf[MAXDATASIZE];
  40.   struct hostent *he;
  41.   struct sockaddr_in server;
  42.   
  43.   
  44.   
  45.   if (argc != 2) {
  46.     printf("Usage: %s \"COMMAND\"\n",argv[0]);
  47.     exit(0);
  48.   }
  49.   
  50.   he = gethostbyname("10.57.220.70");
  51.   fd = socket(AF_INET, SOCK_STREAM, 0);
  52.   bzero(&server, sizeof(server));
  53.   server.sin_family = AF_INET;
  54.   server.sin_port = htons(PORT);
  55.   server.sin_addr = *((struct in_addr *)he->h_addr);

  56.   int ret = connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr));
  57.   
  58.   //for send
  59.   string data;
  60.   int cmdid = 1000;
  61.   char szTemp[1024]={'\0'};
  62.   gamesrv::LuaMsg p;
  63.   p.set_account("123");
  64.   p.set_msg("hideto.bj@gmail.com");
  65.   p.SerializeToString(&data);
  66.   

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

  68.   int len = 4+4;
  69.   memmove(szTemp+8,data.c_str(),data.length());
  70.   len +=data.length();
  71.   *(int*)(szTemp) = htonl(len);
  72.   ret =send(fd, szTemp, len, 0);
  73.   
  74.   memset(buf,0,sizeof(buf));
  75.   numbytes = recv(fd, buf, 8, 0);
  76.   numbytes = ntohl(*(int*)(buf))-8;
  77.   ret = recv(fd, buf, numbytes, 0);
  78.   
  79.   buf[numbytes] = '\0';
  80.   data = buf;
  81.  
  82.   google::protobuf::Message* reply = createMessage("gamesrv.RepLuaMsg");
  83.    
  84.   reply->ParseFromString(data);
  85.   gamesrv::RepLuaMsg* rep = (gamesrv::RepLuaMsg*)reply;
  86.   cout << "People: " << endl;
  87.   cout << "ID: " << rep->account() << endl;
  88.   cout << "Email: " << rep->msg() << endl;
  89.   string mm = rep->msg();
  90.   close(fd);
  91.   
  92.   
  93.   
  94.   return 0;
  95. }
对应的proto文件LuaCmd.proto

点击(此处)折叠或打开

  1. package gamesrv;


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

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

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




阅读(18723) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~