У меня есть клиентское приложение, в котором мне нужно получать HTTP-запросы с длительным сроком выполнения от сервера. Я отправляю команду, и после получения заголовка ответа мне нужно просто получать данные json, разделенные \r\n
, до тех пор, пока соединение не будет разорвано.
Мне удалось адаптировать boost beast пример клиента, чтобы отправить сообщение, получить заголовок, проанализировать его и получить ответы от сервера. Однако мне не удалось найти способ сериализации данных, чтобы я мог обрабатывать сообщения json.
Ближайшую демонстрацию проблемы можно найти в этот пример реле. В этом примере (p
- синтаксический анализатор, sr
- сериализатор, input
- входной поток сокета и output
- выходной поток сокета) после чтения заголовка http у нас есть цикл, который непрерывно читает с сервера:
do
{
if(! p.is_done())
{
// Set up the body for writing into our small buffer
p.get().body().data = buf;
p.get().body().size = sizeof(buf);
// Read as much as we can
read(input, buffer, p, ec);
// This error is returned when buffer_body uses up the buffer
if(ec == error::need_buffer)
ec = {};
if(ec)
return;
// Set up the body for reading.
// This is how much was parsed:
p.get().body().size = sizeof(buf) - p.get().body().size;
p.get().body().data = buf;
p.get().body().more = ! p.is_done();
}
else
{
p.get().body().data = nullptr;
p.get().body().size = 0;
}
// Write everything in the buffer (which might be empty)
write(output, sr, ec);
// This error is returned when buffer_body uses up the buffer
if(ec == error::need_buffer)
ec = {};
if(ec)
return;
}
while(! p.is_done() && ! sr.is_done());
Вот несколько вещей, которые я здесь не понимаю:
- Мы закончили читать заголовок. Почему нам нужен boost beast, а не boost asio, чтобы читать необработанное сообщение tcp? Когда я попытался сделать это (как с async_read, так и с async_read_some), я получил бесконечное количество чтений нулевого размера.
- Документация по парсеру говорит (в конце страницы), что новый экземпляр необходим для каждого сообщения, но я не вижу этого в примере.
- Поскольку чтение сообщений TCP не работает, есть ли способ преобразовать данные парсера / сериализатора в какую-то строку? Даже записать его в текстовый файл в стиле FIFO, чтобы я мог обработать его какой-нибудь json-библиотекой? Я не хочу использовать другой сокет, как в примере.
Функцию boost::beast::buffers()
не удалось скомпилировать для парсера и сериализатора, а для парсера нет функции потребления, а потребление сериализатора, похоже, предназначено для определенных частей сообщения http, которые запускают assert, если я делаю это для body()
.
Кроме того, я также не смог получить согласованные порции данных из парсера и буфера с помощью старой школы std::copy
. Кажется, я не понимаю, как объединить данные, чтобы получить поток данных. Использование буфера с .consume()
в любой момент при получении данных приводит к ошибке need buffer
.
Я был бы очень признателен, если бы кто-нибудь объяснил логику того, как все это должно работать вместе.