PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Example/Network/ProtoBuf/ProtoBuf/ProtoBuf.cpp

http://iocpframework.googlecode.com/
C++ | 328 lines | 225 code | 93 blank | 10 comment | 23 complexity | 8195f507c4d3856dcdd79f1d6cedb9c9 MD5 | raw file
  1. // ProtoBuf.cpp : ??????????????
  2. //
  3. #include "stdafx.h"
  4. #include "Codec.hpp"
  5. #include "Dispatcher.hpp"
  6. #include "Server.hpp"
  7. #include <iostream>
  8. using std::cout;
  9. using std::endl;
  10. #include "test.pb.h"
  11. #pragma comment(lib, "libprotobuf")
  12. void print(const std::string& buf)
  13. {
  14. printf("encoded to %zd bytes\n", buf.c_str());
  15. for (size_t i = 0; i < buf.length(); ++i)
  16. {
  17. unsigned char ch = static_cast<unsigned char>(buf[i]);
  18. printf("%2zd: 0x%02x %c\n", i, ch, isgraph(ch) ? ch : ' ');
  19. }
  20. }
  21. using namespace async;
  22. void TestQuery()
  23. {
  24. typedef ProtobufCodec<network::Tcp::Socket> DefaultProtoBuf;
  25. muduo::Query query;
  26. query.set_id(1);
  27. query.set_questioner("Chen Shuo");
  28. query.add_question("Running?");
  29. std::string buf;
  30. DefaultProtoBuf::FillBuffer(buf, query);
  31. print(buf);
  32. size_t len = 0;
  33. memcpy(&len, buf.data(), sizeof(len));
  34. DefaultProtoBuf::ErrorCode errorCode = DefaultProtoBuf::kNoError;
  35. MessagePtr message = DefaultProtoBuf::Parse(buf.data() + sizeof(size_t), len, &errorCode);
  36. assert(errorCode == DefaultProtoBuf::kNoError);
  37. assert(message != NULL);
  38. message->PrintDebugString();
  39. assert(message->DebugString() == query.DebugString());
  40. std::tr1::shared_ptr<muduo::Query> newQuery = std::tr1::static_pointer_cast<muduo::Query>(message);
  41. assert(newQuery != NULL);
  42. }
  43. void testAnswer()
  44. {
  45. typedef ProtobufCodec<network::Tcp::Socket> DefaultProtoBuf;
  46. muduo::Answer answer;
  47. answer.set_id(1);
  48. answer.set_questioner("Chen Shuo");
  49. answer.set_answerer("blog.csdn.net/Solstice");
  50. answer.add_solution("Jump!");
  51. answer.add_solution("Win!");
  52. std::string buf;
  53. DefaultProtoBuf::FillBuffer(buf, answer);
  54. print(buf);
  55. size_t len = 0;
  56. memcpy(&len, buf.data(), sizeof(len));
  57. DefaultProtoBuf::ErrorCode errorCode = DefaultProtoBuf::kNoError;
  58. MessagePtr message = DefaultProtoBuf::Parse(buf.data() + sizeof(size_t), len, &errorCode);
  59. assert(errorCode == DefaultProtoBuf::kNoError);
  60. assert(message != NULL);
  61. message->PrintDebugString();
  62. assert(message->DebugString() == answer.DebugString());
  63. std::tr1::shared_ptr<muduo::Answer> newAnswer = std::tr1::static_pointer_cast<muduo::Answer>(message);
  64. assert(newAnswer != NULL);
  65. }
  66. void testEmpty()
  67. {
  68. muduo::Empty empty;
  69. typedef ProtobufCodec<network::Tcp::Socket> DefaultProtoBuf;
  70. std::string buf;
  71. DefaultProtoBuf::FillBuffer(buf, empty);
  72. print(buf);
  73. size_t len = 0;
  74. memcpy(&len, buf.data(), sizeof(len));
  75. DefaultProtoBuf::ErrorCode errorCode = DefaultProtoBuf::kNoError;
  76. MessagePtr message = DefaultProtoBuf::Parse(buf.data() + sizeof(size_t), len, &errorCode);
  77. assert(message != NULL);
  78. message->PrintDebugString();
  79. assert(message->DebugString() == empty.DebugString());
  80. }
  81. void redoCheckSum(std::string& data, int len)
  82. {
  83. int checkSum = 0;/*sockets::hostToNetwork32(static_cast<int32_t>(
  84. ::adler32(1,
  85. reinterpret_cast<const Bytef*>(data.c_str()),
  86. static_cast<int>(len - 4))));*/
  87. data[len-4] = reinterpret_cast<const char*>(&checkSum)[0];
  88. data[len-3] = reinterpret_cast<const char*>(&checkSum)[1];
  89. data[len-2] = reinterpret_cast<const char*>(&checkSum)[2];
  90. data[len-1] = reinterpret_cast<const char*>(&checkSum)[3];
  91. }
  92. void testBadBuffer()
  93. {
  94. typedef ProtobufCodec<network::Tcp::Socket> DefaultProtoBuf;
  95. muduo::Empty empty;
  96. empty.set_id(43);
  97. std::string buf;
  98. DefaultProtoBuf::FillBuffer(buf, empty);
  99. // print(buf);
  100. size_t len = 0;
  101. memcpy(&len, buf.data(), sizeof(len));
  102. {
  103. std::string data(buf.data(), len);
  104. DefaultProtoBuf::ErrorCode errorCode = DefaultProtoBuf::kNoError;
  105. MessagePtr message = DefaultProtoBuf::Parse(data.c_str() + sizeof(size_t), len-1, &errorCode);
  106. assert(message == NULL);
  107. assert(errorCode == DefaultProtoBuf::kCheckSumError);
  108. }
  109. {
  110. std::string data(buf.data(), len);
  111. DefaultProtoBuf::ErrorCode errorCode = DefaultProtoBuf::kNoError;
  112. data[len-1]++;
  113. MessagePtr message = DefaultProtoBuf::Parse(data.c_str() + sizeof(size_t), len, &errorCode);
  114. assert(message == NULL);
  115. assert(errorCode == DefaultProtoBuf::kCheckSumError);
  116. }
  117. {
  118. std::string data(buf.data(), len);
  119. DefaultProtoBuf::ErrorCode errorCode = DefaultProtoBuf::kNoError;
  120. data[0]++;
  121. MessagePtr message = DefaultProtoBuf::Parse(data.c_str() + sizeof(size_t), len, &errorCode);
  122. assert(message == NULL);
  123. assert(errorCode == DefaultProtoBuf::kCheckSumError);
  124. }
  125. }
  126. int g_count = 0;
  127. void onMessage(const network::Tcp::Socket& conn, const MessagePtr& message)
  128. {
  129. g_count++;
  130. }
  131. void testOnMessage()
  132. {
  133. typedef ProtobufCodec<network::Tcp::Socket> DefaultProtoBuf;
  134. muduo::Query query;
  135. query.set_id(1);
  136. query.set_questioner("Chen Shuo");
  137. query.add_question("Running?");
  138. std::string buf1;
  139. DefaultProtoBuf::FillBuffer(buf1, query);
  140. muduo::Empty empty;
  141. empty.set_id(43);
  142. empty.set_id(1982);
  143. std::string buf2;
  144. DefaultProtoBuf::FillBuffer(buf2, empty);
  145. size_t totalLen = buf1.size() + buf2.size();
  146. std::string all;
  147. all.append(buf1.data(), buf1.size());
  148. all.append(buf2.data(), buf2.size());
  149. assert(all.size() == totalLen);
  150. network::SocketPtr sock;
  151. network::Tcp::Socket conn(sock);
  152. DefaultProtoBuf codec(onMessage);
  153. for (size_t len = 0; len <= totalLen; ++len)
  154. {
  155. std::string input;
  156. input.append(all.data(), len);
  157. g_count = 0;
  158. codec.OnMessage(conn, iocp::Buffer(input));
  159. int expected = len < buf1.size() ? 0 : 1;
  160. if (len == totalLen) expected = 2;
  161. assert(g_count == expected);
  162. // printf("%2zd %d\n", len, g_count);
  163. input.append(all.data() + len, totalLen - len);
  164. codec.OnMessage(conn, iocp::Buffer(input));
  165. assert(g_count == 2);
  166. }
  167. }
  168. typedef std::tr1::shared_ptr<muduo::Query> QueryPtr;
  169. typedef std::tr1::shared_ptr<muduo::Answer> AnswerPtr;
  170. void onQuery(async::network::Tcp::Socket&, const QueryPtr& message)
  171. {
  172. cout << "onQuery: " << message->GetTypeName() << endl;
  173. }
  174. void onAnswer(async::network::Tcp::Socket&, const AnswerPtr& message)
  175. {
  176. cout << "onAnswer: " << message->GetTypeName() << endl;
  177. }
  178. void onUnknownMessageType(async::network::Tcp::Socket&, const MessagePtr& message)
  179. {
  180. cout << "onUnknownMessageType: " << message->GetTypeName() << endl;
  181. }
  182. void TestDispatcher()
  183. {
  184. dispatch::ProtobufDispatcher<network::Tcp::Socket> dispatcher(onUnknownMessageType);
  185. dispatcher.RegisterMessageCallback<muduo::Query>(onQuery);
  186. dispatcher.RegisterMessageCallback<muduo::Answer>(onAnswer);
  187. async::network::SocketPtr sock;
  188. async::network::Tcp::Socket conn(sock);
  189. QueryPtr query(new muduo::Query);
  190. AnswerPtr answer(new muduo::Answer);
  191. std::tr1::shared_ptr<muduo::Empty> empty(new muduo::Empty);
  192. dispatcher.OnProtobufMessage(conn, query);
  193. dispatcher.OnProtobufMessage(conn, answer);
  194. dispatcher.OnProtobufMessage(conn, empty);
  195. struct NotMessage
  196. {};
  197. std::tr1::shared_ptr<NotMessage> not(new NotMessage);
  198. //dispatcher.RegisterMessageCallback<NotMessage>(onQuery);
  199. }
  200. void OnQuery(Session &session, const MessagePtr& message)
  201. {
  202. std::cout << "onQuery:\n" << message->GetTypeName() << message->DebugString();
  203. session.Send(*message);
  204. //conn->shutdown();
  205. }
  206. void OnAnswer(Session &session, const MessagePtr& message)
  207. {
  208. std::cout << "onAnswer: " << message->GetTypeName();
  209. session.Send(*message);
  210. }
  211. void TestServer()
  212. {
  213. async::iocp::IODispatcher io;
  214. Server svr(io, 5050);
  215. using namespace std::tr1::placeholders;
  216. svr.Register<muduo::Query>(std::tr1::bind(&OnQuery, _1, _2));
  217. svr.Register<muduo::Answer>(std::tr1::bind(&OnAnswer, _1, _2));
  218. svr.Start();
  219. system("pause");
  220. svr.Stop();
  221. }
  222. int _tmain(int argc, _TCHAR* argv[])
  223. {
  224. GOOGLE_PROTOBUF_VERIFY_VERSION;
  225. TestQuery();
  226. testAnswer();
  227. testEmpty();
  228. testBadBuffer();
  229. //testOnMessage();
  230. TestDispatcher();
  231. TestServer();
  232. google::protobuf::ShutdownProtobufLibrary();
  233. system("pause");
  234. return 0;
  235. }