Boost.beast websocket - 如何为 io_context.run() 创建待处理的 async_read() queue/work?
Boost.beast websocket - How to make a pending async_read() queue/work for io_context.run()?
完全菜鸟在这里通过使用 Websocket 的 IoT 项目学习 c++。
至此,稍微成功修改了这个例子beast async_client_ssl与服务器握手。
我的问题是 ioc.run() 运行 在初始回调后停止工作并退出。
两年前我遇到了与 post 相同的问题。
Boost.best websocket ios.run() exits after sending a request and receiving one reply
上面链接 post 的答案非常简单(1. 和 2.),但我仍然不知道如何实现它。
1.在不阅读您的代码的情况下,了解 运行() 方法在没有未决工作时终止。例如,您的读取方法需要排队一个新的读取。
2。将 async_read() 移动到一个单独的函数,比方说 do_read(),并在 on_read() 的末尾以及当前位置调用它。
post里提问的人也显得很疑惑,不过这两个回答之后,就没有再解释了。那么,有没有人可以帮助我,或许可以提供一个简单的代码片段?
在 some other noob's previous post 代码中的 on_read() 中,我添加了 async_read() 如下所示。
void on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
io_in_pr34ogress_ = false; // end of write/read sequence
boost::ignore_unused(bytes_transferred);
if(ec)
return fail(ec, "read");
else
std::cout << "on_read callback : " << boost::beast::buffers(buffer_.data()) << std::endl;
// Clear the Buffer
//~ buffer_ = {};
buffer_.consume(buffer_.size());
ws_.async_read(buffer_, std::bind(&session::on_read, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
但没有希望。 ioc.run 刚刚结束。那么如何正确地做上述 1. 和 2. 的回答呢?
谢谢!
----------------更新于 2021 年 10 月 25 日---------------- ---
@sehe 的回答与执行者合作。
为此,我不得不将 boost 版本从 1.67 升级到 1.7 以上(我使用的是 1.74)。这解决了我的问题,但如果有人为那里的人们提供了适用于 1.67 的有效解决方案,请分享这个想法:)
好吧,最简单的就是加一个work_guard
。更合乎逻辑的做法是将 thread_pool 作为执行上下文。
打一个工作警卫:
boost::asio::io_context ioc;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
work = make_work_guard(ioc.get_executor());
(或简称 auto work = make_work_guard(...);
).
如果在某个时候你想要 运行 return,释放工作守卫:
work.reset();
线程池
前一种略过了“明显”的事实,即您需要另一个线程来 run()
服务 或 reset()
工作守卫。
相反,我建议首先将线程的 运行 留给 Asio:
boost::asio::thread_pool ioc(1);
这和 io_context
一样是一个 执行上下文 :
int main()
{
// +-----------------------------+
// | Get azure access token |
// +-----------------------------+
static std::string const accessToken =
"wss://sehe797979.webpubsub.azure.com/client/hubs/"
"Hub?access_token=*************************************"
"**********************************************************************"
"**********************************************************************"
"**********************************************************************"
"************************************************************";
// get_access_token();
// +--------------------------+
// | Websocket payload struct |
// +--------------------------+
struct Payload payload = {0, "", "text", "test", "joinGroup"};
// +---------------------------------+
// | Websocket connection parameters |
// +---------------------------------+
std::string protocol = "wss://";
std::string host = "sehe797979.webpubsub.azure.com";
std::string port = "443";
std::string text = json_payload(payload);
auto endpointSubstringIndex = protocol.length() + host.length();
// Endpoint
std::string endpoint = accessToken.substr(endpointSubstringIndex);
//std::cout << "Endpoint : " << endpoint << std::endl;
// The io_context is required for all I/O
boost::asio::thread_pool ioc(1);
// The SSL context is required, and holds certificates
ssl::context ctx{ssl::context::sslv23_client};
// This holds the root certificate used for verification
load_root_certificates(ctx);
// Launch the asynchronous operation
std::shared_ptr<session> ws_session =
std::make_shared<session>(ioc.get_executor(), ctx);
ws_session->open(host, port, endpoint);
// Run the I/O service. The call will return when the socket is closed.
// Change the payload type
payload.type = "sendToGroup";
// +--------------+
// | Send Message |
// +--------------+
// Get the input and update the payload data
while (getline(std::cin, payload.data)) {
// Send the data over WSS
ws_session->write(json_payload(payload));
}
ioc.join();
}
这需要对 session
构造函数进行最少的更改以采用执行程序而不是 io_context&
:
template <typename Executor>
explicit session(Executor executor, ssl::context& ctx)
: resolver_(executor)
, ws_(executor, ctx)
{
}
这是一个完全独立的编译演示 Live On Coliru
完全菜鸟在这里通过使用 Websocket 的 IoT 项目学习 c++。 至此,稍微成功修改了这个例子beast async_client_ssl与服务器握手。
我的问题是 ioc.run() 运行 在初始回调后停止工作并退出。 两年前我遇到了与 post 相同的问题。 Boost.best websocket ios.run() exits after sending a request and receiving one reply
上面链接 post 的答案非常简单(1. 和 2.),但我仍然不知道如何实现它。
1.在不阅读您的代码的情况下,了解 运行() 方法在没有未决工作时终止。例如,您的读取方法需要排队一个新的读取。
2。将 async_read() 移动到一个单独的函数,比方说 do_read(),并在 on_read() 的末尾以及当前位置调用它。
post里提问的人也显得很疑惑,不过这两个回答之后,就没有再解释了。那么,有没有人可以帮助我,或许可以提供一个简单的代码片段?
在 some other noob's previous post 代码中的 on_read() 中,我添加了 async_read() 如下所示。
void on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
io_in_pr34ogress_ = false; // end of write/read sequence
boost::ignore_unused(bytes_transferred);
if(ec)
return fail(ec, "read");
else
std::cout << "on_read callback : " << boost::beast::buffers(buffer_.data()) << std::endl;
// Clear the Buffer
//~ buffer_ = {};
buffer_.consume(buffer_.size());
ws_.async_read(buffer_, std::bind(&session::on_read, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
但没有希望。 ioc.run 刚刚结束。那么如何正确地做上述 1. 和 2. 的回答呢?
谢谢!
----------------更新于 2021 年 10 月 25 日---------------- ---
@sehe 的回答与执行者合作。 为此,我不得不将 boost 版本从 1.67 升级到 1.7 以上(我使用的是 1.74)。这解决了我的问题,但如果有人为那里的人们提供了适用于 1.67 的有效解决方案,请分享这个想法:)
好吧,最简单的就是加一个work_guard
。更合乎逻辑的做法是将 thread_pool 作为执行上下文。
打一个工作警卫:
boost::asio::io_context ioc;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
work = make_work_guard(ioc.get_executor());
(或简称 auto work = make_work_guard(...);
).
如果在某个时候你想要 运行 return,释放工作守卫:
work.reset();
线程池
前一种略过了“明显”的事实,即您需要另一个线程来 run()
服务 或 reset()
工作守卫。
相反,我建议首先将线程的 运行 留给 Asio:
boost::asio::thread_pool ioc(1);
这和 io_context
一样是一个 执行上下文 :
int main()
{
// +-----------------------------+
// | Get azure access token |
// +-----------------------------+
static std::string const accessToken =
"wss://sehe797979.webpubsub.azure.com/client/hubs/"
"Hub?access_token=*************************************"
"**********************************************************************"
"**********************************************************************"
"**********************************************************************"
"************************************************************";
// get_access_token();
// +--------------------------+
// | Websocket payload struct |
// +--------------------------+
struct Payload payload = {0, "", "text", "test", "joinGroup"};
// +---------------------------------+
// | Websocket connection parameters |
// +---------------------------------+
std::string protocol = "wss://";
std::string host = "sehe797979.webpubsub.azure.com";
std::string port = "443";
std::string text = json_payload(payload);
auto endpointSubstringIndex = protocol.length() + host.length();
// Endpoint
std::string endpoint = accessToken.substr(endpointSubstringIndex);
//std::cout << "Endpoint : " << endpoint << std::endl;
// The io_context is required for all I/O
boost::asio::thread_pool ioc(1);
// The SSL context is required, and holds certificates
ssl::context ctx{ssl::context::sslv23_client};
// This holds the root certificate used for verification
load_root_certificates(ctx);
// Launch the asynchronous operation
std::shared_ptr<session> ws_session =
std::make_shared<session>(ioc.get_executor(), ctx);
ws_session->open(host, port, endpoint);
// Run the I/O service. The call will return when the socket is closed.
// Change the payload type
payload.type = "sendToGroup";
// +--------------+
// | Send Message |
// +--------------+
// Get the input and update the payload data
while (getline(std::cin, payload.data)) {
// Send the data over WSS
ws_session->write(json_payload(payload));
}
ioc.join();
}
这需要对 session
构造函数进行最少的更改以采用执行程序而不是 io_context&
:
template <typename Executor>
explicit session(Executor executor, ssl::context& ctx)
: resolver_(executor)
, ws_(executor, ctx)
{
}
这是一个完全独立的编译演示 Live On Coliru