Boost asio io_content 运行 非阻塞
Boost asio io_content run non-blocking
目前我正在编写一个包含在 C# 库中的 C++ Websocket 客户端库。
我正在使用 Boost Beast 进行 websocket 连接。
现在我在握手完成时开始 async_read,这样 websocket 就不会断开连接。
问题是 io_content 阻塞线程,因此 C# 程序停止执行,直到 async_read 超时并且 io_content returns。但我希望 C# 程序继续执行。
我试图在一个线程中执行connect函数,但是有一个问题,C#程序调用的下一个函数是写操作并且它崩溃了,因为connect函数仍在连接...
library.cpp:
void OpenConnection(char* id)
{
std::cout << "Opening new connection..." << std::endl;
std::shared_ptr<Session> session = std::make_shared<Session>();
session->connect();
sessions.emplace(std::string(id), std::move(session));
}
session.cpp:
void Session::connect()
{
resolver.async_resolve(
"websocket_uri",
"443",
beast::bind_front_handler(
&Session::on_resolve,
shared_from_this()));
ioc.run();
}
on_resolve、on_connect、on_handshake...与此处相同:https://www.boost.org/doc/libs/1_70_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
除非on_handshake函数:
void Session::on_handshake(beast::error_code ec)
{
if (ec)
return fail(ec, "handshake");
ws.async_read(buffer, beast::bind_front_handler(&Session::on_read, shared_from_this()));
}
和 on_read 函数:
void Session::on_read(beast::error_code ec, std::size_t bytes_transfered)
{
boost::ignore_unused(bytes_transfered);
if (ec)
return fail(ec, "read");
std::cout << "Got message" << std::endl;
onMessage(Message::parseMessage(beast::buffers_to_string(buffer.data())));
ws.async_read(buffer, beast::bind_front_handler(&Session::on_read, shared_from_this()));
}
和 on_write 函数:
void Session::on_write(beast::error_code ec, std::size_t bytes_transfered)
{
boost::ignore_unused(bytes_transfered);
if (ec)
return fail(ec, "write");
queue.erase(queue.begin());
if (!queue.empty())
{
ws.async_write(net::buffer(queue.front()->toString()), beast::bind_front_handler(&Session::on_write, shared_from_this()));
}
}
C#程序(测试用):
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void OpenConnection(string id);
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void CloseConnection(string id);
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void GenerateQRCode(string id);
static void Main(string[] args)
{
string id = "test";
OpenConnection(id);
GenerateQRCode(id);
}
现在是我的问题,我该如何实现?
我已经被这个问题卡住了 3 天了,慢慢地绝望了。
已经谢谢了:)
您需要使用 async_read_some
而不是 async_read
来自提升
async_read_some function is used to asynchronously read data from the stream socket. The function call always returns immediately.
The read operation may not read all of the requested number of bytes.
Consider using the async_read function if you need to ensure that the
requested amount of data is read before the asynchronous operation
completes.
基本上成功调用async_read_some
可能只读取一个字节,
或者它可能填满整个缓冲区,或介于两者之间的任何地方。这
另一方面,asio::async_read
函数可用于确保整个
缓冲区在操作完成之前被填满。 async_write_some
和 asio::async_write
函数具有相同的关系。
这里有一个很好的 example 如何使用 async_read_some
目前我正在编写一个包含在 C# 库中的 C++ Websocket 客户端库。
我正在使用 Boost Beast 进行 websocket 连接。
现在我在握手完成时开始 async_read,这样 websocket 就不会断开连接。
问题是 io_content 阻塞线程,因此 C# 程序停止执行,直到 async_read 超时并且 io_content returns。但我希望 C# 程序继续执行。
我试图在一个线程中执行connect函数,但是有一个问题,C#程序调用的下一个函数是写操作并且它崩溃了,因为connect函数仍在连接...
library.cpp:
void OpenConnection(char* id)
{
std::cout << "Opening new connection..." << std::endl;
std::shared_ptr<Session> session = std::make_shared<Session>();
session->connect();
sessions.emplace(std::string(id), std::move(session));
}
session.cpp:
void Session::connect()
{
resolver.async_resolve(
"websocket_uri",
"443",
beast::bind_front_handler(
&Session::on_resolve,
shared_from_this()));
ioc.run();
}
on_resolve、on_connect、on_handshake...与此处相同:https://www.boost.org/doc/libs/1_70_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
除非on_handshake函数:
void Session::on_handshake(beast::error_code ec)
{
if (ec)
return fail(ec, "handshake");
ws.async_read(buffer, beast::bind_front_handler(&Session::on_read, shared_from_this()));
}
和 on_read 函数:
void Session::on_read(beast::error_code ec, std::size_t bytes_transfered)
{
boost::ignore_unused(bytes_transfered);
if (ec)
return fail(ec, "read");
std::cout << "Got message" << std::endl;
onMessage(Message::parseMessage(beast::buffers_to_string(buffer.data())));
ws.async_read(buffer, beast::bind_front_handler(&Session::on_read, shared_from_this()));
}
和 on_write 函数:
void Session::on_write(beast::error_code ec, std::size_t bytes_transfered)
{
boost::ignore_unused(bytes_transfered);
if (ec)
return fail(ec, "write");
queue.erase(queue.begin());
if (!queue.empty())
{
ws.async_write(net::buffer(queue.front()->toString()), beast::bind_front_handler(&Session::on_write, shared_from_this()));
}
}
C#程序(测试用):
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void OpenConnection(string id);
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void CloseConnection(string id);
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void GenerateQRCode(string id);
static void Main(string[] args)
{
string id = "test";
OpenConnection(id);
GenerateQRCode(id);
}
现在是我的问题,我该如何实现?
我已经被这个问题卡住了 3 天了,慢慢地绝望了。
已经谢谢了:)
您需要使用 async_read_some
而不是 async_read
来自提升
async_read_some function is used to asynchronously read data from the stream socket. The function call always returns immediately.
The read operation may not read all of the requested number of bytes. Consider using the async_read function if you need to ensure that the requested amount of data is read before the asynchronous operation completes.
基本上成功调用async_read_some
可能只读取一个字节,
或者它可能填满整个缓冲区,或介于两者之间的任何地方。这
另一方面,asio::async_read
函数可用于确保整个
缓冲区在操作完成之前被填满。 async_write_some
和 asio::async_write
函数具有相同的关系。
这里有一个很好的 example 如何使用 async_read_some