一个带有超时、执行器和速率限制策略的流套接字包装器。
定义在头文件 <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 要求的类型,表示要用于 basic stream socket 的协议。一个常见的选择是 |
|
一个满足 Executor 要求的类型,用于提交所有尚未关联执行器的完成处理程序。如果省略此类型,则将使用默认的 |
不同的对象:安全。
共享对象:不安全。应用程序还必须确保所有异步操作都在同一个隐式或显式 strand 中执行。