【发布时间】:2019-04-10 10:14:41
【问题描述】:
我有一个客户端应用程序,我需要从服务器接收 http“长时间运行的请求”。我发送一个命令,得到响应的头部后,我只需要接收由\r\n分隔的json数据,直到连接终止。
我设法调整boost beast client example 来发送消息并接收标头并解析它并接收来自服务器的响应。但是,我未能找到一种方法来序列化数据以便处理 json 消息。
可以在this relay example 中找到最接近该问题的演示。在那个例子中(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),我得到了一个大小为零的无限读取。
- parser 的文档说(在页面末尾)每条消息都需要一个新实例,但我在示例中没有看到。
- 由于 tcp 消息读取不起作用,有没有办法将解析器/序列化器数据转换为某种字符串?甚至以先进先出的方式将其写入文本文件,以便我可以使用一些 json 库来处理它?我不想像示例那样使用另一个套接字。
函数boost::beast::buffers() 无法为解析器和序列化程序编译,并且解析器没有消费函数,序列化程序的消费似乎是针对消息的特定 http 部分,如果我这样做会触发一个断言对于body()。
除此之外,我还未能从解析器和缓冲区中获取一致的数据块,使用老式的std::copy。我似乎不明白如何将数据组合在一起以获取数据流。在接收数据的任何时候使用.consume() 使用缓冲区会导致need buffer 错误。
我非常感谢有人解释所有这些应该如何协同工作的逻辑。
【问题讨论】:
标签: c++ http boost boost-asio boost-beast