【问题标题】:What are the requirements to read and write from an http stream (in boost::beast)?从 http 流(在 boost::beast 中)读取和写入的要求是什么?
【发布时间】:2019-08-27 21:16:58
【问题描述】:

我想使用 boost::beast 来读写 etcd。首先,我希望能够使用 boost beast 做these examples。它们很容易用 curl 完成。 Etcd 可以看作是一个键/值存储。使用boost::beast client example 可以轻松完成设置/获取(示例页面中的放置/范围)的功能。没有问题。

但是“看”,我不明白。根据docs 的说法,watch 是一个连续流,与其他会话不同,后者是在检索结果后立即终止的会话。 curl 示例显示了在手表仍处于活动状态时更改值和现场响应。我应该使用同一个流来执行与该手表相关的所有事情,包括停止它。

我的问题大致是:如何在 boost::beast 中实现这一点

假设来自client example I submit ioc.run through a thread

std::thread t(&std::iocontext::run, &ioc);
t.detach();

现在我可以在主线程中完全控制客户端。我应该创建新的 http 请求并通过套接字对象在async_write 中提交它们吗?但是,如果我这样做,我将失去 boost::beast 的功能,即用漂亮的http::request<http::string_body> 包装 http 标头。我应该手动创建标题吗?还是我应该只发送带有某种行终止符的json 以指示消息已结束?通信协议是什么样的?

boost::beast 的例子会很棒。

【问题讨论】:

    标签: c++ boost-asio json-rpc etcd boost-beast


    【解决方案1】:

    看起来 etcd 使用“长时间运行的请求”。为此,您想使用http::read_header[1] 或http::async_read_header[2] 来获取响应头,然后在循环中使用http::read_some[3] 或http::async_read_some[4] 来读取部分响应体。为此,您需要使用专为此类事情设计的http::buffer_body[5]。文档中的 HTTP Relay 示例[6] 演示了buffer_body 的使用,可以适应处理长时间运行的请求。

    [1]https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__read_header/overload2.html

    [2]https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__async_read_header.html

    [3]https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__read_some/overload2.html

    {4]https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__async_read_some.html

    [5]https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__buffer_body.html

    [6]https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/more_examples/http_relay.html

    【讨论】:

    • 感谢您的惠妮。这很有帮助。我从 http 中继示例中遇到了一件事。有没有办法使用序列化器数据并将其转换为字符串?如何以 FIFO 方式从该示例中获取数据?在示例中,它将序列化数据立即写入输出套接字。我找不到将序列化程序数据转换为字符串并使用它的方法。函数buffers_to_string 对它不起作用。
    • 我还想指出,在检索到标头后,交换的字符串只是由\r\n分隔的json。我能够用 curl 验证这一点。我不明白为什么我们需要一个解析器,因为没有更多的 http 标头存在。一方面,我无法理解如何以 FIFO 方式使用带/不带序列化器的解析器来检索 json 数据。另一方面,我尝试直接socket_.async_read_some(),因为我认为原始数据就是我所需要的,并且创建了一个无限循环的大小 = 0 的读取。我很感激这方面的一些提示。
    • 您需要一个解析器,因为如果传输编码是“分块的”怎么办? Beast 并不提前知道您的消息正文将始终是简单的。无论如何,如果你不想使用解析器,并且你知道正文不是块编码的,你总是可以自己从套接字中读取字节。但是,请注意,传递给野兽 HTTP 读取算法的动态缓冲区可能包含正文的一部分。所以解析器指示header完成后,需要先消费这个buffer中的所有数据,然后再继续从socket中读取。
    • 如果您想要字符串中的正文(我建议使用string_view,以避免不必要的分配、复制和释放循环),那么只需从您的指针和大小构造一个字符串。听起来您无法理解缓冲区的工作原理,我建议您阅读boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/…
    • 我没有使用string_view(我现在就是这样),但这基本上是我昨天在做的事情。我使用std::copy 来复制缓冲区指针及其大小。用解析器和序列化器主体和缓冲区尝试了这个,两者都导致数据块重复。以前我不知道分块是什么意思,我刚学了它,可能重复解释了它。但是,根据您的解释,当从序列化程序中获取数据时,它不应该有任何重复,但是当我从正文中获取指针时,我看到它在这里发生了。 [...]
    猜你喜欢
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 2019-02-27
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    相关资源
    最近更新 更多