Чтение непрерывного потока объектов json с помощью boost / socket iostreams - PullRequest
0 голосов
/ 17 февраля 2019

У меня есть клиент (который я могу изменить), который в настоящее время отправляет данные в виде непрерывного потока объектов 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(), но я полностью открыт для других подходов.

...