一个流套接字包装器,具有超时、执行器和速率限制策略。
定义于头文件 <boost/beast/core/basic_stream.hpp>
中
template< class Protocol, class Executor = net::any_io_executor, class RatePolicy = unlimited_rate_policy> class basic_stream
名称 |
描述 |
---|---|
端点类型。 |
|
与流关联的执行器的类型。 |
|
协议类型。 |
|
将流类型重新绑定到另一个执行器。 |
|
底层套接字的类型。 |
名称 |
描述 |
---|---|
异步地将流连接到指定的端点。 |
|
异步地读取一些数据。 |
|
异步地写入一些数据。 |
|
basic_stream [构造函数] |
构造函数。 |
取消与套接字关联的所有异步操作。 |
|
关闭定时流。 |
|
将流连接到指定的端点。 |
|
为后续的逻辑操作设置超时。 |
|
为后续的逻辑操作设置超时。 |
|
禁用后续逻辑操作的超时。 |
|
获取与对象关联的执行器。 |
|
移动赋值(已删除)。 |
|
返回与对象关联的速率策略。 |
|
读取一些数据。 |
|
释放底层套接字的所有权。 |
|
返回对底层套接字的引用。 |
|
写入一些数据。 |
|
~basic_stream [析构函数] |
析构函数。 |
此流包装了一个 net::basic_stream_socket
以提供以下功能
尽管流支持多个并发的未完成异步操作,但流对象不是线程安全的。 调用者负责确保一次只有一个线程访问该流。 这包括网络实现访问流及其底层套接字的时间。 为了满足此线程安全要求,所有异步操作都必须由流在同一隐式 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); }
同步函数的行为与包装的 net::basic_stream_socket
的行为相同。 执行阻塞调用时,超时不可用。
类型 |
描述 |
---|---|
|
满足 Protocol 要求的类型,表示用于基本流套接字的协议。 常见的选择是 |
|
满足 Executor 要求的类型,用于提交所有尚未关联执行器的完成处理程序。 如果省略此类型,则将使用默认值 |
不同对象:安全。
共享对象:不安全。 应用程序还必须确保所有异步操作都在同一隐式或显式 strand 中执行。