当前位置:   article > 正文

【网络】自定义协议 | 序列化和反序列化 | 以tcpServer为例_tcp序列化和反序列化

tcp序列化和反序列化

本文首发于 慕雪的寒舍

以tcpServer的计算器服务为例,实现一个自定义协议

阅读本文之前,请先阅读 tcpServer

本文完整代码详见 Gitee

1.重谈tcp

注意,当下所对tcp的描述都是以简单、方便理解起见,后续会对tcp协议进行深入解读

1.1 链接

我们知道,tcp是面向连接的,客户端和服务端要先建立链接,才能开始通信

  • 在链接过程中,tcp采用三次握手
  • 在断线过程中,tcp采用四次挥手

举个日常生活中的栗子,帮助理解3次握手和4次挥手

image-20230211103933999

1.2 信息发送

假如我们现在需要发送结构化数据,那应该怎么办?

我们知道,tcp是面向字节流的,也就是其能够发送任意数据。也能够发送C语言结构体的二进制数据;

  • 但能发送,就代表我们可以这么干吗?
  • 答案自然是不行

不同平台,对结构体对齐的配置不同,大小端不同,其最终对我们字节流的解析也就不一样。如果采用直接发送结构体数据的方式来通信,适配性极低,我们的客户端和服务端都会被限制在当前的系统环境中运行;

可是,哪怕是同一个系统,其内部对大小端的配置也有可能改变!到时候我们的代码恐怕就无法运行了!

同理,在当初编写C语言通讯录的代码的时候,也不能采用直接将结构体数据写入文件的方式。后续代码升级、环境改变,都可能导致我们存在文件中的数据失效,这肯定是我们不希望看到的情况。

所以,为了解决这个问题,我们就应该将数据进行序列化之后再发送,客户端接收到信息后,进行反序列化解析出数据!

2.序列化和反序列化

2.1 简介

所谓序列化,就是将结构化的数据(可以暂时理解为c的结构体)转换成字符串的方式,发送出去

struct date
{
    int year;
    int month;
    int day;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

比如上面这个日期结构体,我们要想将其序列化,就可以用一个很简单的方式拼接成一个字符串(序列化)

year-month-day
  • 1

客户端收到这个字符串之后,就可以通过查找分隔符-的方式,取出三个变量,将其转成int后存放回结构体(反序列化)

这样,我们就算是规定了一个序列化和反序列化的方式,也就是一个简单的协议


2.2 编码解码

这里还会出现另外一个问题,我要怎么知道我已经读取完毕了一个序列化后的数据呢?

2000-12-10
10000-01-01
  • 1
  • 2

如上,假设有一天,我们的年变成了五位数;这时候,服务端要怎么知道自己是否读取完毕了一个完整的序列化数据呢?

这就需要我们做好规定,将前n字节作为标识长度的数据。接收到数据后,先取出前n个字节,读取道此次消息的长度m,再往后读取m个字节的数据,成功取出完整的字符串;

  • 这个过程可以称作编码和解码的过程

为了区分标识长度的数据和实际需要的序列化内容,我们可以在之中加上分隔符\t;但这也需要我们确认,传输的数据本身不能带上\t,否则会产生一系列的问题

10\t2000-12-10\t
11\t10000-01-01\t
  • 1
  • 2

以上的这一系列工作,都是协议定制的一部分!我们给服务端和客户端规定了一个序列化和反序列化的方式,让二者通信规避掉了平台的限制。毕竟任何平台对字符串解码出来的数据都会是相同的!

下面就用一个计算器的服务,来演示一下吧

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/988084
推荐阅读
相关标签