У меня есть клиент (который я могу изменить), который в настоящее время отправляет данные в виде непрерывного потока объектов JSON без разделителей без пробелов между объектами, например:
{ "value": 123 }
{ "value": 456 }
{ "value": 789 }
I'mпытаюсь научиться использовать деревья свойств boost и сокеты iostreams для записи принимающей стороны, но у меня возникают проблемы с чтением более одного объекта 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
немедленно вернется один разполный объект был прочитан и проанализирован, так что приведенные выше примеры данных должны были пройти через этот цикл три раза и прочитать + напечатать три объекта.
То, что на самом деле происходит, так это то, что read_json
не возвращается до тех пор, покаудаленное соединение закрыто:
- Если я попытаюсь отправить несколько объектов JSON, как только я отправлю
{
второго объекта, read_json
выдаст ошибку «мусор после данных». - Если я отправляю один объект JSON, затем закрываю соединение (удаленная сторона), тогда
read_json
возвращает это значение, а затем выдает «ожидаемое значение» во второй раз. - Я знаю, что это не такпроблема с буферизацией: я использую клиент telnet для подключения и отладки, и я могу на 100% подтвердить его полное чтение и обработку по одному байту за раз без буферизации.
Мой вопрос:Как я могу прочитать этот непрерывный поток объектов?Возможно, есть какой-то способ установить разделитель между объектами или какой-то вариант, чтобы read_json
возвращался сразу после каждого объекта?
Я также не хочу слишком больших накладных расходов между объектами, поскольку это будет довольно большой поток пропускной способности, если я в конечном итоге использую повышение в моем реальном проекте.Я бы также предпочел, чтобы что-то получалось усилить с минимально возможной хитростью: моя цель - использовать 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()
, но я полностью открыт для других подходов.