6.9 xml 与 json 格式协议

xml 和 json 这两种格式由于其良好的自我解释性,是开发中使用的非常广泛的两种数据格式。一个 xml 格式的示例如下所示:

<?xml version="1.0" encoding="utf-8"?>
<SkinList>
  <Skin>
    <SkinID>0</SkinID>
    <SkinName>默认皮肤</SkinName>
    <SkinPath>Skin0\</SkinPath>
  </Skin>
  <Skin>
    <SkinID>1</SkinID>
    <SkinName>冰凉清爽</SkinName>
    <SkinPath>Skin1\</SkinPath>
  </Skin>
  <CurSkinID>0</CurSkinID>
</SkinList>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

一个 json 格式的示例如下:

{
    "userid": 1001,
    "username": "xiaofang",
    "nickname": "小方",
    "facetype": 0,
    "gender": 1,
    "birthday": 19900101,
    "signature": "生活需要很多的力气呀。xx",
    "clienttype": 1
}
1
2
3
4
5
6
7
8
9
10

关于 xml 和 json 的格式介绍,不是本节的重点内容,如果还不熟悉的读者可以去网络上查找相关的资料来学习一下。

那么 xml 和 json 格式可以单独用来作为网络通信协议吗?

当然可以,但是一般单独使用 xml 或者 json 格式作为网络通信协议的服务非常少,其原因是在给数据包分界得到一个个完整的包时非常不方便。

如果读者理解了前面 《TCP 协议是流式协议》和《如何解决粘包问题》章节中介绍内容,可能已经知道答案了。无论是 xml 还是 json 格式,如果单独作为协议,一般由于业务数据内容不同,每个包的长度不一样。那么在 TCP 流式数据中只能采取固定结束符的方式来分割,对于不确定长度的 xml 和 json,在频繁进行数据交换的网络通信程序中,每次解包前都得遍历一次 xml 或 json 字符串以寻找特定的包结束符。例如,对于上面的 xml 示例,就是在流式数据中寻找 </SkinList> 字符串以作为一个 xml 格式的包结束符,对于上面的 json 格式,仅仅寻找 json 结束的花括号(})容易造成误判的,还得在这基础上加上其他限定标记,例如,json 的最后一个节点可以加一个特殊字段标志作为结束标记,以上述 json 为例,在其末尾增加一个 endFlag 标志后变成如下形式:

{
    "userid": 1001,
    "username": "xiaofang",
    "nickname": "小方",
    "facetype": 0,
    "gender": 1,
    "birthday": 19900101,
    "signature": "生活需要很多的力气呀。xx",
    "clienttype": 1,
    "endFlag": 0
}

1
2
3
4
5
6
7
8
9
10
11
12

这样当该 json 作为一个数据包时,在判断包结束标志时可以通过寻找 "“endFlag”: 0" 加一个 “}” 这样的字符串作为包分界符号。但这种方法很不灵活,json 在某些系统或库中解析时各个字段的位置顺序可能会被调整,也就是说,像 "“endFlag”: 0" 这样的字段可能会被调整到 json 中的非末尾位置;另外 json 被格式化后某些字段值后面会被追加 “\n” 或 “\r\n” 这样的换行符,这就给程序寻找指定包结束符带来了困扰。

所以通常情况下,xml 或者 json 格式不会被单独作为协议格式,而是会作为某个协议的一部分出现,例如如下格式:

struct msg
{
	//在消息头header中说明整个包的大小,减去header、cmd和seq的大小就是buf的长度
	//即是xml或者json的长度
	msgheader header;
	int32_t	  cmd;
	int32_t   seq;
	char*     buf;	//buf是一个字符串,其格式可以是一个 xml 或者 json
};
1
2
3
4
5
6
7
8
9

凡事可能存在特例,业界也有使用 xml 格式的协议,例如 XMPP,有兴趣的读者可以通过XMPP官网了解一下。

上次更新: 2025/05/19, 16:52:22

社区交流

讨论与留言

前往 GitHub Issues →

本留言区仅对应当前文章,欢迎补充观点、提出问题或帮助修正文中疏漏。 留言由 GitHub/Gitalk 提供,需要使用 GitHub 登录。

最近更新
第 1 课:专栏导论与安全边界
07-01
第 3 课:安装编译与调试环境
07-01
第 4 课:第三方库下载、编译与依赖管理
07-01
更多文章>