awe*_*ome 5 c++ boost asynchronous boost-asio
所以我创建了一个socket类,它使用boost :: asio库来进行异步读写.它有效,但我有几个问题.
这是一个基本的代码示例:
class Socket
{
public:
void doRead()
{
m_sock->async_receive_from(boost::asio::buffer(m_recvBuffer), m_from, boost::bind(&Socket::handleRecv, this, boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred()));
}
void handleRecv(boost::system::error_code e, int bytes)
{
if (e.value() || !bytes)
{
handle_error();
return;
}
//do something with data read
do_something(m_recvBuffer);
doRead(); //read another packet
}
protected:
boost::array<char, 1024> m_recvBuffer;
boost::asio::ip::udp::endpoint m_from;
};
Run Code Online (Sandbox Code Playgroud)
程序似乎会读取数据包,处理它,然后准备读取另一个数据包.简单.但是,如果我设置一个线程池呢?下一次调用应该doRead()在处理读取数据之前还是之后?似乎如果它被放在之前do_something(),程序可以立即开始读取另一个数据包,如果它被放在后面,那么线程就会做任何事情do_something(),这可能需要一段时间.如果我把它放在doRead()处理之前,这是否意味着在m_readBuffer我处理它时数据可能会改变?
另外,如果我正在使用async_send_to(),我是否应该将要发送的数据复制到临时缓冲区中,因为实际发送可能要么在数据超出范围之后才会发生?即
void send()
{
char data[] = {1, 2, 3, 4, 5};
m_sock->async_send_to(boost::buffer(&data[0], 5), someEndpoint, someHandler);
} //"data" gets deallocated, but the write might not have happened yet!
Run Code Online (Sandbox Code Playgroud)
此外,当套接字关闭时,将调用handleRecv并显示一条错误,指示它已被中断.如果我做
Socket* mySocket = new Socket()...
...
mySocket->close();
delete mySocket;
Run Code Online (Sandbox Code Playgroud)
它会导致错误吗,因为有可能mySocket在handleRecv()被调用/完成之前被删除?
这里有很多问题,我将尝试一次解决一个问题。
但是如果我设置一个线程池呢?
io_service::run() 将线程池与 Boost.Asio 一起使用的传统方法是从多个线程调用。请注意,这并不是一个一刀切的答案,可能存在可扩展性或性能问题,但这种方法是迄今为止最容易实现的。Stackoverflow 上有很多类似的问题,提供更多信息。
下一次调用 doRead 应该在处理读取数据之前还是之后?看起来,如果它放在 do_something() 之前,程序可以立即开始读取另一个数据包,如果它放在后面,则线程会被困在 do_something 所做的事情上,这可能需要一段时间。
这实际上取决于do_something()需要做什么m_recvBuffer。如果您希望与usingdo_something()并行调用,您可能需要复制.doRead()io_service::post()m_recvBuffer
如果我将 doRead() 放在处理之前,这是否意味着 m_readBuffer 中的数据在我处理时可能会发生变化?
正如我之前提到的,是的,这可能而且将会发生。
另外,如果我使用的是
async_send_to(),我是否应该将要发送的数据复制到临时缓冲区中,因为实际的发送可能要等到数据超出范围后才会发生?
正如文档所描述的,调用者(您)需要确保缓冲区在异步操作期间保持在范围内。正如您所怀疑的,您当前的示例会调用未定义的行为,因为data[]会超出范围。
此外,当套接字关闭时,
handleRecv()将调用 并显示错误,表明它已被中断。
如果您希望继续使用套接字,请使用cancel()来中断未完成的异步操作。否则,close()会起作用。在任一情况下传递给未完成的异步操作的错误都是boost::asio::error::operation_aborted。