• 【Linux网络编程】序列化与反序列化


    我们网络收发数据实际上只能接收到字符串,但是在现实生活中描述一个客观物体都是以很多属性来描述的,所以在网络中结构体类型的数据更常见,那我们如何发送结构体数据呢?

    这里就涉及到协议的概念了。我们想象一个场景,在特种兵执行任务时,他们有特定的战术手语,这样他们就能根据手语进行相应的战术配合了。所以协议也是一样,客户端和服务器都遵循相同的协议,以某种格式把字符串变成结构体或把结构体变成字符串。这个过程中就是序列化与反序列化。

     序列化:结构体类型数据转化成字节序

    反序列化:字节序转化成结构体类型数据

    话不多说,看图

    服务器利用套接字接收请求,进行反序列化后,对请求进行业务处理,处理完成把结果生成响应

    然后序列化发送给客户端。自然,客户端接收响应也必须反序列化。

    简易网络计算器协议协议部分代码:定制自己的协议,确定数据格式。

    下面还利用到了Json这种数据转换格式语言。

    1. #pragma once
    2. #include
    3. #include
    4. #include "Util.hpp"
    5. #include
    6. #include
    7. // 利用条件编译,在这里定义一个宏,如果定义了就走a,否则就走b,这相当于是一个开关
    8. // #define HAHA 666
    9. // 给网络版本计算器制定协议
    10. namespace Protocol_ns
    11. {
    12. #define SEP " "
    13. #define SEP_LEN strlen(SEP) // 不能用sizeof
    14. #define HEADER_SEP "\r\n"
    15. #define HEADER_SEP_LEN strlen("\r\n")
    16. // 请求/响应 = 报头\r\n有效载荷\r\n
    17. // "10 + 20" => "7"\r\n""10 + 20"\r\n
    18. std::string AddHeader(std::string &str)
    19. {
    20. std::string s = std::to_string(str.size());
    21. s += HEADER_SEP;
    22. s += str;
    23. s += HEADER_SEP;
    24. return s;
    25. }
    26. // 读取一个完整的报文;
    27. int ReadPackage(int sock, std::string &inbuffer, std::string *package)
    28. {
    29. char buffer[1024];
    30. ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0); // 读取
    31. if (n <= 0)
    32. return -1;
    33. buffer[n] = 0; // 添加字符串末尾'/0';
    34. inbuffer += buffer;
    35. size_t pos = inbuffer.find(HEADER_SEP);
    36. if (pos == std::string::npos)
    37. return 0; // 虽然读到了数据,但是不存在一个完整的报文,应该继续读取
    38. std::string lenStr = inbuffer.substr(0, pos);
    39. int len = Util::toInt(lenStr);
    40. int targetPackageLen = HEADER_SEP_LEN * 2 + len + lenStr.size();
    41. if (inbuffer.size() < targetPackageLen)
    42. return 0; // 虽然读到了数据,但是不存在一个完整的报文,应该继续读取
    43. *package = inbuffer.substr(0, targetPackageLen); // 提取到了整个报文
    44. inbuffer.erase(0, targetPackageLen); // 从inbuffer中直接移除整个报文
    45. return len; // 返回有效载荷长度
    46. }
    47. // "7"\r\n""10 + 20"\r\n => "10 + 20"
    48. void RemoveHeader(std::string *package, int len)
    49. {
    50. size_t pos = (*package).find(HEADER_SEP);
    51. *package = (*package).erase(0, pos);
    52. *package = (*package).erase(0, HEADER_SEP_LEN);
    53. *package = (*package).substr(0, len);
    54. }
    55. // Request && Response都要提供序列化和反序列化功能
    56. class Request
    57. {
    58. public:
    59. Request() {}
    60. Request(int x, int y, char op)
    61. : _x(x), _y(y), _op(op)
    62. {
    63. }
    64. // struct -> string
    65. bool Serialization(std::string *outStr)
    66. {
    67. *outStr = "";
    68. #ifdef HAHA
    69. std::string x_string = std::to_string(_x);
    70. std::string y_string = std::to_string(_y);
    71. // 手动序列化
    72. *outStr = x_string + SEP + _op + SEP + y_string; // outstr在这里是输出型参数;
    73. #else
    74. Json::Value root; // Value: 一种万能对象, 接受任意的kv类型
    75. root["x"] = _x;
    76. root["y"] = _y;
    77. root["op"] = _op;
    78. Json::StyledWriter writer; // Writer是用来进行序列化的,struct->string
    79. *outStr = writer.write(root);
    80. #endif
    81. return true;
    82. }
    83. // string->struct
    84. bool Deserialization(const std::string &inStr)
    85. {
    86. #ifdef HAHA
    87. std::vector result;
    88. Util::StringSplit(inStr, SEP, &result); // 对序列化数据进行分割,这相当于是一种解释;
    89. if (result.size() != 3)
    90. return false;
    91. if (result[1].size() != 1)
    92. return false;
    93. _x = Util::toInt(result[0]);
    94. _y = Util::toInt(result[2]);
    95. _op = result[1][0];
    96. #else
    97. Json::Value root;
    98. Json::Reader reader; // Reader:用来进行反序列化的。
    99. reader.parse(inStr, root);
    100. _x = root["x"].asInt();
    101. _y = root["y"].asInt();
    102. _op = root["op"].asInt();
    103. #endif
    104. return true;
    105. }
    106. ~Request() {}
    107. public:
    108. int _x;
    109. int _y;
    110. char _op;
    111. };
    112. class Response
    113. {
    114. public:
    115. Response() {}
    116. Response(int result, int code)
    117. : _result(result), _code(code)
    118. {
    119. }
    120. bool Serialization(std::string *outStr)
    121. {
    122. *outStr = "";
    123. #ifdef HAHA
    124. std::string _result_string = std::to_string(_result);
    125. std::string _code_string = std::to_string(_code);
    126. // 手动序列化
    127. *outStr = _result_string + SEP + _code_string; // outstr在这里是输出型参数;
    128. #else
    129. Json::Value root;
    130. root["result"] = _result;
    131. root["code"] = _code;
    132. Json::StyledWriter writer; // writer::用来进行序列化的;
    133. *outStr = writer.write(root);
    134. #endif
    135. return true;
    136. }
    137. bool Deserialization(const std::string &inStr)
    138. {
    139. #ifdef HAHA
    140. std::vector result;
    141. Util::StringSplit(inStr, SEP, &result); // 对序列化数据进行分割,这相当于是一种解释;
    142. if (result.size() != 2)
    143. return false;
    144. _result = Util::toInt(result[0]);
    145. _code = Util::toInt(result[1]);
    146. #else
    147. Json::Value root;
    148. Json::Reader reader;
    149. reader.parse(inStr,root);
    150. _result=root["result"].asInt();
    151. _code=root["code"].asInt();
    152. #endif
    153. return true;
    154. }
    155. ~Response() {}
    156. public:
    157. int _result;
    158. int _code; // 0 success, 1,2,3,4代表不同的错误码;
    159. };
    160. }

  • 相关阅读:
    【精讲】Es6的数组的扩展方法,对象的扩展方法,字符串扩展方法,?. 对象层级深
    Java 类型通配符下限以及案例说明(八)
    语法练习:pos_neg
    notepad++下载 地址真实有效
    家电软装记录
    数据标注典型案例,景联文科技如何助力企业搭建数据方案
    软件需求分析一般应确定的是用户对软件的(功能需求和非功能需求 ),结构化设计是一种面向(数据流 )的设计方法
    Reactive判断的API,toRef & toRefs,ref其他的API,customRef
    TypeScript(基础篇)day01
    RabbitMQ系列【10】死信队列
  • 原文地址:https://blog.csdn.net/zzxz8/article/details/132921351