使用boost / socket iostream读取连续的json对象流

时间:2019-02-17 19:44:49

标签: c++ json boost boost-asio boost-propertytree

我有一个客户端(可以修改),该客户端当前以连续的JSON对象流的形式发送数据,而对象之间没有非空格分隔符,例如:

{ "value": 123 }
{ "value": 456 }
{ "value": 789 }

我正在尝试学习如何使用boost的属性树和套接字iostream来编写接收端,但是一次读取多个JSON对象时遇到了麻烦。目前,我只是这样子(其中stream是连接到客户端的tcp::iostream):

while (true) {

    // read object
    property_tree::ptree data;
    property_tree::read_json(stream, data);

    // print object to console
    property_tree::write_json(cout, data, true);

}

我的期望是,read_json将在读取并解析完整对象后立即返回,因此上述示例数据将在该循环中运行3次,并读取并打印3次对象。

实际上似乎正在发生的事情是read_json在关闭远程连接之前不会返回:

  • 如果我尝试发送多个JSON对象,则当我发送第二个对象的{时,read_json会引发错误“数据后垃圾”。
  • 如果我发送一个JSON对象,然后关闭连接(远程),则read_json返回该值,然后第二次抛出“期望值”。
  • 我知道这不是一个缓冲问题:我正在使用telnet客户端进行连接和调试,并且我可以100%确认一次完全读取和处理一个字节而没有缓冲。

我的问题是:如何读取连续的对象流?也许有某种方法可以在对象之间设置定界符,或者某种选择使read_json在每个对象之后立即返回?

我也不希望对象之间有太多开销,因为如果我最终在实际项目中使用boost的话,这将是一个相当高的带宽流。我还希望尽可能地减少混淆,以提高性能:我的目标是在接收端使用read_json,在发送端使用write_json,并保持代码简洁明了(这基本上是一种组合的学习经验+稍后对生产代码的提升进行评估)-我愿意采用其他读取/写入方法,但最终我确实希望将数据存储在property_tree中。我还需要能够在单个对象到达后尽快处理它们。所以我不能做任何涉及大量缓冲/分组的事情。


发布此代码后,我继续进行挖掘,最终得到了boost中的这段代码:

    void finish() {
        skip_ws();
        if (!src.done()) {
            parse_error("garbage after data");
        }
    }

与(...为简便起见,我删除了):

void read_json_internal(...)
{
    ...
    parser.parse_value(); // <-- reads the object
    parser.finish(); // <-- the finish() from the above snippet
}

上下文很复杂,但可以说这是在解析结束时发生的事情(只需使用您喜欢的IDE跟随read_json后面的符号,您将很快获得该代码)。令人沮丧的是,它似乎不必要地受到限制。因此,看来read_json不可能直接实现。

我将继续挖掘,看是否有某种方法可以让我更直接地使用内部解析器,或者至少不用调用finish()就能做到这一点,但是我完全可以接受其他方法。

0 个答案:

没有答案