Boost C++ 库

……是世界上最受推崇、设计最精良的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ Coding Standards

basic_stream - Boost C++ 函数库
PrevUpHomeNext

一个带有超时、执行器和速率限制策略的流套接字包装器。

纲要

定义在头文件 <boost/beast/core/basic_stream.hpp>

template<
    class Protocol,
    class Executor = net::any_io_executor,
    class RatePolicy = unlimited_rate_policy>
class basic_stream
类型

名称

描述

endpoint_type

执行器类型。

executor_type

与流关联的执行器的类型。

protocol_type

协议类型。

rebind_executor

将流类型重新绑定到另一个执行器。

socket_type

底层套接字的类型。

成员函数

名称

描述

async_connect

异步连接流到指定的终结点。

通过异步尝试序列中的每个终结点来建立连接。

async_read_some

异步读取一些数据。

async_write_some

异步写入一些数据。

basic_stream [构造函数]

构造函数。

移动构造函数。

cancel

取消与套接字关联的所有异步操作。

close

关闭计时流。

connect

连接流到指定的终结点。

通过尝试序列中的每个终结点来建立连接。

expires_after

为后续的逻辑操作设置超时。

expires_at

为后续的逻辑操作设置超时。

expires_never

禁用后续逻辑操作的超时。

get_executor

获取与对象关联的执行器。

operator=

移动赋值(已删除)。

rate_policy

返回与对象关联的速率策略。

read_some

读取一些数据。

release_socket

释放对底层套接字的拥有权。

socket

返回底层套接字的引用。

write_some

写入一些数据。

~basic_stream [析构函数]

析构函数。

描述

该流包装了一个 net::basic_stream_socket 以提供以下功能:

  • 可以为流关联一个执行器,该执行器将用于调用任何尚未关联执行器的完成处理程序。这实现了对 [P1322R0] Networking TS enhancement to enable custom I/O executors 的支持。
  • 可以为每次执行读取、写入或连接的逻辑异步操作指定超时。
  • 可以为流关联一个速率策略,以通过策略的接口实现速率限制。

尽管该流支持多个并发的未完成异步操作,但流对象本身并非线程安全的。调用者负责确保在任何时候只有一个线程访问该流。这包括在网络实现访问流及其底层套接字的时候。为了满足此线程安全要求,所有异步操作必须在同一个隐式 strand(只有一个线程 net::io_context::run)内,或者在同一个显式 strand(例如 net::strand 的实例)内执行。

具有显式关联执行器的完成处理程序(例如使用 net::bind_executor 产生的)将由流使用关联的执行器调用。否则,完成处理程序将由流构造时关联的执行器调用。与此流一起使用的执行器类型必须满足以下要求:

  • 提交给执行器的函数对象不得与彼此并发运行。

执行器类型 net::strand 满足这些要求。在流类模板中使用 strand 作为执行器,提供了一个额外的便利:无需在每次单独的调用函数中指定 strand。

与其它流包装器不同,底层套接字是通过 socket 成员函数而不是 next_layer 来访问的。这导致在调用 get_lowest_layer 时返回的是 basic_stream

用法

要使用此流,请声明该类的实例。然后,在每次需要超时的逻辑操作之前,调用 expires_after 并传入一个时长,或者调用 expires_at 并传入一个时间点。或者,调用 expires_never 来禁用后续逻辑操作的超时。逻辑操作是指对超时流的任何直接或间接调用异步读取、异步写入或异步连接函数的任何一系列操作。

当设置了超时并且执行混合操作(例如,同时包含读取和写入的操作)时,超时将应用于所包含操作的所有中间异步操作。这允许在将流算法传递给具有设置超时的超时流时,对那些并非专门为支持超时而设计的流算法应用超时。

当发生超时时,套接字将被关闭,取消任何待处理的 I/O 操作。这些被取消的操作的完成处理程序将被调用,并带有关联的错误 beast::error::timeout

示例

此函数在有超时的情况下读取 HTTP 请求,然后使用不同的超时发送 HTTP 响应。

void process_http_1 (tcp_stream& stream, net::yield_context yield)
{
    flat_buffer buffer;
    http::request<http::empty_body> req;

    // Read the request, with a 15 second timeout
    stream.expires_after(std::chrono::seconds(15));
    http::async_read(stream, buffer, req, yield);

    // Calculate the response
    http::response<http::string_body> res = make_response(req);

    // Send the response, with a 30 second timeout.
    stream.expires_after (std::chrono::seconds(30));
    http::async_write (stream, res, yield);
}

上面的示例可以通过一个简单的修改,使用一个单一的超时来表达。接下来的函数首先读取一个 HTTP 请求,然后发送 HTTP 响应,使用一个适用于整个组合读写操作的单一超时。

void process_http_2 (tcp_stream& stream, net::yield_context yield)
{
    flat_buffer buffer;
    http::request<http::empty_body> req;

    // Require that the read and write combined take no longer than 30 seconds
    stream.expires_after(std::chrono::seconds(30));

    http::async_read(stream, buffer, req, yield);

    http::response<http::string_body> res = make_response(req);
    http::async_write (stream, res, yield);
}

某些流算法,例如 ssl::stream::async_handshake,会执行读取和写入操作。在调用此类复合流算法的启动函数之前设置的超时将应用于整个复合操作。例如,可以按如下方式设置执行 SSL 握手的超时:

void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
{
    // Require that the SSL handshake take no longer than 10 seconds
    stream.expires_after(std::chrono::seconds(10));

    stream.async_handshake(net::ssl::stream_base::client, yield);
}
阻塞 I/O

同步函数与包装的 net::basic_stream_socket 的行为完全相同。在执行阻塞调用时,无法使用超时。

模板参数

类型

描述

Protocol

一个满足 Protocol 要求的类型,表示要用于 basic stream socket 的协议。一个常见的选择是 net::ip::tcp

执行器

一个满足 Executor 要求的类型,用于提交所有尚未关联执行器的完成处理程序。如果省略此类型,则将使用默认的 net::any_io_executor

线程安全

不同的对象:安全。

共享对象:不安全。应用程序还必须确保所有异步操作都在同一个隐式或显式 strand 中执行。

参见

PrevUpHomeNext