我有一个客户端(可以修改),该客户端当前以连续的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
在关闭远程连接之前不会返回:
{
时,read_json
会引发错误“数据后垃圾”。read_json
返回该值,然后第二次抛出“期望值”。我的问题是:如何读取连续的对象流?也许有某种方法可以在对象之间设置定界符,或者某种选择使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()
就能做到这一点,但是我完全可以接受其他方法。>