【问题标题】:C - How to determine the amount of bytes for JSON messagesC - 如何确定 JSON 消息的字节数
【发布时间】:2018-05-15 01:19:45
【问题描述】:

我正在开发一个基于 Linux 的项目,该项目由一个用 C 编写的“核心”应用程序和一个可能用 Python 编写的 Web 服务器组成。核心和 Web 服务器必须能够通过 TCP/IP 相互通信。我的重点是 C 语言的核心应用程序。

由于核心和 Web 服务器使用不同的编程语言,我正在寻找一种在两种语言中都易于使用的消息协议。目前我认为 JSON 是一个不错的选择。然而,我的问题不是关于消息协议,而是关于我如何确定从套接字读取(并可能发送到)的字节数,特别是在使用 JSON 或 XML 等消息协议时。

据我了解,无论您使用 JSON、XML 还是其他一些消息协议,都不能在消息本身中包含消息的大小,因为为了解析消息,您需要整个消息,因此需要提前知道它的大小。请注意,“消息”是指根据使用的消息协议格式化的数据。

我一直在思考和阅读解决这个问题的方法,得出了以下两种可能性:

  1. 确定消息的最大可能大小,例如 500 字节,并在此基础上确定缓冲区大小,例如 512 字节,并为每条消息添加填充,以便发送 512 字节;
  2. 在“纯文本”中添加每条消息的大小。如果大小存储在 Int(4 个字节)中,则接收方首先从套接字读取 4 个字节,并使用这 4 个字节确定接下来要读取多少字节以获取实际消息;

因为我阅读过的所有提供的解决方案都不是专门针对某些消息协议(如 JSON)的使用,所以我认为我可能遗漏了一些东西。

那么,我提供的两种可能性中哪一种是最好的,或者,我不知道这个问题的其他解决方案吗?

亲切的问候。

【问题讨论】:

  • 欢迎来到 SO。您必须知道,对于 TCP/IP,您不能只依赖接收一条消息。由于连接是流,您可能会收到少于或多于一条消息。您必须准备阅读一部分并等待收到剩余的部分。
  • 您实际上需要一个高级协议才能收集完整的 JSON 消息。但是由于 JSON 是面向文本的,因此您也可以使用特殊的非 ascii 字节作为消息分隔符,因为它们不能包含在 JSON 消息中。
  • 如果你允许的话,或者更确切地说是非 Unicode。如果要选择文本编码,最好使用 utf-8。
  • @Gerhardh:谢谢。消息是指我作为程序员指定的消息。假设此消息大小为 X 字节。那么,是不是你从socket中读取X字节,以阻塞的方式,这样当你读完的时候,你已经读取了X字节,也就是一条消息?
  • @SergeBallesta 不正确 - JSON 可以原生携带 UTF-8,并且不会对其进行特殊编码。

标签: c json sockets tcp


【解决方案1】:

这是流(包括 TCP 流)遇到的经典问题,通常称为“消息边界问题”。你可以搜索比我在这里给出的更详细的答案。

要确定边界,您有一些选择:

  • 如您所说,使用填充固定长度。除非您有非常小的消息,否则不建议使用。
  • 前面加上你说的大小。如果您想在不浪费太多字节的情况下获得花哨并支持大型消息,则可以使用可变长度数量,在这里您可以使用位来确定是否读取更多字节的大小。 @alnitak 提到了我忽略的 cmets 的一个缺点,那就是在知道大小之前无法开始发送。
  • 绑定了一些你在其他地方不使用的字节(JSON 和 XML 是纯文本的,所以 '\0' 与 ASCII 或任何 UTF 一起使用)。接收端简单但速度较慢,因为您必须以这种方式扫描每个字节。
  • 编辑:JSON、XML 和许多其他格式也可以即时解析以确定边界(例如,每个 { 必须在 JSON 中用 } 关闭),但我没有看到任何优势这样做。

如果这不仅仅是一种学习体验,您可以改为使用现有协议为您完成这一切。例如 HTTP(低效)或 gRPC(更高效)。

编辑:我最初说过必须包含校验和来处理数据包丢失,尽管 TCP 是完全错误的...... TCP 在正确接收到这些数据包之前不会前进,所以这不是问题。 IDK 我在想什么。

【讨论】:

  • 您似乎不知道 TCP 是如何工作的。您不能在 TCP 中“丢失”这样的数据包。操作系统会检测到丢失的数据包并自动重传。
  • 我的错,我完全失误了,忘记了 TCP 不会在没有收到最后一条消息的情况下前进。正在编辑...
  • @Alnitak JSON 规范说必须转义控制字符,如果您转到tools.ietf.org/html/rfc7159 并搜索“必须转义的字符除外”。我见过的 C JSON 库使用空终止字符串,就像 C 中的许多库一样,如果你尝试解码包含空字节的字符串,Python 会出错。
  • 我错过了 json.org 上的“除了控制字符”!无论哪种方式,在这种情况下我仍然不会使用分隔符。
猜你喜欢
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 2011-02-02
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
相关资源
最近更新 更多