1

我正在使用一个接受 HTTP POST 请求以及 URL 形式编码的查询数据作为有效负载的 API。来自服务器的响应是分块的,每个块包含一个 JSON 对象。我正在尝试通过 C# 中的块读取和解析服务器的响应,以便我可以获取块,使用 Newtonsoft 将其转换,然后执行我需要的任何处理。服务器每次查询返回一个未知的记录数 - 它可能是 0 条记录,也可能是数千个块。

我对典型解决方案的研究和测试HttpClient表明,这些库仅通过将所有内容连接到单个响应流中来“处理”块。此外,我读过其他帖子,表明如果服务器没有 100% 遵循规范,甚至有可能在流结束时出现异常。

我考虑了以下解决方案,但似乎没有一个是最佳的:

  1. 从 HTTP 响应中逐个字符、计数{}字符读取流,以查找 JSON 对象的开始和结束。每次}找到关闭时,解析对象。这是非常丑陋、低效且不通用的——它假设每个 JSON 响应都是一个对象,并且需要更改 wuold,例如,如果服务器发送一个 JSON 数组 ( [and ]),或者甚至每个块只发送一个 JSON 字符串。

  2. 完全跳过 HttpRequest/HttpClient 并在原始套接字中执行所有操作。然后,我可以解析块大小,从套接字流中准确读取那么多字节,并进行相应的解析。这会起作用,除了感觉像很多“重新发明轮子”,因为我必须为 POST 正文、标头解析、SSL/TLS 等实现 URL 编码。这一切基本上都被 HttpClient“解决”了,所以实现如果没有其他原因,我自己又觉得这是个坏主意,因为我可以很容易地引入一个解析错误。

  3. 由于服务器为每个块发送一个 JSON 对象,读取整个响应,然后查找}{并认为这些是 JSON 对象的分割点(因为在实际的 JSON 中,,两个对象之间会存在一个列表的一部分)。这充其量感觉是不可靠的——它假设每个块的 JSON 对象的两侧都没有空格。这也是低效的,因为如果服务器要返回数百万条记录,则需要将整个响应存储在 RAM 中。包含数百万条记录的响应的总大小可能超过 1GB,跨越数百个块。虽然这对于具有大量 RAM 的机器来说不一定是问题,但它是一种不必要的低效方法,用于解析设计为可流式传输的数据。

理想的场景是某种按块读取 HTTP 流的枚举器,因为 API 正在生成块,其中每个块恰好代表一个 JSON 对象。这是我考虑在选项 2 中实现的内容,但同样,这似乎需要大量重新发明轮子,并且可能会引入严重的错误。第二个最佳选择是在 HttpClient 执行请求并解析标头之后从 HttpClient获取原始的底层套接字流的方法——换句话说,一种获取包含块大小和分隔符的流的方法,所以然后我可以解析直接流式传输,提取块大小,并且基本上执行上面的#2,但无需编写我自己的 HTTP 实现。

实现此功能的最佳选择是什么?

4

0 回答 0