class session : public std::enable_shared_from_this<session>
{
...
beast::flat_buffer buffer_; // (Must persist between reads)
http::response<http::string_body> res_;
...
}
void on_write(beast::error_code ec, std::size_t bytes_transferred) {
if (ec)
{
fail(ec, "write");
return try_again();
}
// Receive the HTTP response
http::async_read(
stream_, buffer_, res_,
beast::bind_front_handler(&session::on_read, shared_from_this()));
}
void on_read(beast::error_code ec, std::size_t bytes_transferred) {
if (ec)
{
fail(ec, "read");
return try_again();
}
// Step 1: process response
//
const auto &body_data = res_.body().data();
user_parse_data(net::buffers_begin(body_data), net::buffers_end(body_data));
// Step 2: clean up buffer_
//
buffer_.consume(buffer_.size()); // clean up buffer_ after finishing reading it
// Step 3: continue to write
...
}
在上面的实现中,我仅在成功解析数据后才清理
buffer_
。
问题> 当我在
buffer_
上也遇到错误时,我应该清理 on_read
吗?
void on_read(beast::error_code ec, std::size_t bytes_transferred) {
if (ec)
{
// clean up buffer_
buffer_.consume(buffer_.size()); // Should we do the cleanup here too?
fail(ec, "read");
return try_again();
}
// Step 1: process response
//
const auto &body_data = res_.body().data();
user_parse_data(net::buffers_begin(body_data), net::buffers_end(body_data));
// Step 2: clean up buffer_
//
buffer_.consume(buffer_.size());
// Step 3: continue to write
...
}
// Should we do the cleanup here too?
这完全是在问错误的问题。
首先出现的一个明显问题是“我们是否应该清理读取缓冲区”。
更重要的问题是:你用这个连接做什么?
缓冲区属于连接,因为它代表流数据。
您链接的示例始终会关闭连接。因此,缓冲区在收到响应后就变得无关紧要了——因为连接变得无关紧要。请注意,链接的示例也不在缓冲区上。
你应该清理吗?
consume
之后进行清理!
原因是
http::read
已经
消耗了解析为响应消息一部分的所有数据。即使您希望从同一连接(例如 HTTP 管道)读取更多消息,您也需要以相同的
http::read
开始下一个 http::read
,因为它可能已经包含后续消息的(部分)数据。
出现错误怎么办?如果您在 HTTP 传输过程中出现 IO/解析错误,我预计在大多数情况下 HTTP 协议规范将
HTTP/1 中没有“try_again”。一旦丢失流内容的线程,就无法恢复到“已知状态”。
无论如何,我总是建议关闭失败的 HTTP 会话,因为不这样做会导致消息损坏和安全漏洞。