C++ Boost Asio-使用共享ptr处理解析器和套接字
我有一个类可以通过TCP发送消息。这里是简化的界面:C++ Boost Asio-使用共享ptr处理解析器和套接字,c++,sockets,boost,boost-asio,shared-ptr,C++,Sockets,Boost,Boost Asio,Shared Ptr,我有一个类可以通过TCP发送消息。这里是简化的界面: class CommandScreenshot : public CameraCommand { public: CommandScreenshot(); ~CommandScreenshot(); void Dispatch(boost::shared_ptr<boost::asio::io_service> io_service); private: void resolve_handle
class CommandScreenshot : public CameraCommand
{
public:
CommandScreenshot();
~CommandScreenshot();
void Dispatch(boost::shared_ptr<boost::asio::io_service> io_service);
private:
void resolve_handler(const boost::system::error_code& err,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
};
其他所有操作都将在以下回调函数中完成。io_服务
对象以及相应的线程由另一个类管理(它有一个CommandScreenshot
实例并调用Dispatch
函数)
现在,要使用Boost实现一个简单的TCP连接,您需要一个解析器
和一个套接字
对象,这两个对象都绑定到io_服务
对象。由于此时只传递io\u服务
对象,因此调用函数,我无法在类构造函数中初始化它们。
另外,不可能将它们声明为类成员,然后在函数本身中初始化它们
我的第一个想法是在函数调用时初始化它们,并将它们传递给我的完成处理程序。这意味着每次调用函数时我都会声明这两个对象,并将它们绑定到io\u服务
。然后在async\u resolve
中,我通过boost::bind
添加这两个参数。这意味着我的resolve\u处理程序将需要更多参数,例如:
void resolve_handler(const boost::system::error_code& err,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator,
boost::asio::ip::tcp::resolver resolver,
boost::asio::ip::tcp::socket socket);
我实际上怀疑这是一个体面和公平的解决办法。通常,这些对象应该作为成员保留,而不是被复制——因此我又重新考虑了一下,然后我想到了boost::shared\u ptr
在我的标题中,它现在看起来如下所示:
// Stuff above stays the same
private:
boost::shared_ptr<boost::asio::ip::tcp::resolver> m_resolver;
boost::shared_ptr<boost::asio::ip::tcp::socket> m_socket;
// Stuff below stays the same
//以上内容保持不变
私人:
boost::共享\u ptr m\u解析器;
boost::共享\u ptr m_套接字;
//下面的内容保持不变
其实施将是:
void CommandScreenshot::Dispatch(boost::shared_ptr<boost::asio::io_service> io_service)
{
m_resolver.reset(new boost::asio::ip::tcp::resolver(*io_service));
m_socket.reset(new boost::asio::ip::tcp::socket(*io_service));
boost::asio::ip::tcp::resolver::query query(m_hostname,"http");
m_resolver->async_resolve(query,boost::bind(&CommandScreenshot::resolve_handler,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator));
return;
}
void命令截图::调度(boost::共享的ptr io_服务)
{
重置(新的boost::asio::ip::tcp::resolver(*io_服务));
重置(新的boost::asio::ip::tcp::socket(*io_服务));
boost::asio::ip::tcp::解析器::查询查询(m_主机名,“http”);
m_解析器->异步解析(查询,boost::bind(&CommandScreenshot::resolve_处理程序,this,boost::asio::placeholders::error,boost::asio::placeholders::iterator));
返回;
}
这样,我就不需要复制4个(甚至更多)参数并将它们绑定在一起。当我需要套接字对象时,我可以通过指针(类成员)访问它
现在我的简单问题是->这是正确的方法吗?即使异步部分尚未完成,也可以多次调用该函数。(我知道我应该用互斥锁保护套接字和解析器)。但是每次调用Dispatch
函数时,我都会创建一个新对象,这是否干净呢?reset
调用是否足以消除任何不需要的内存
我知道这是一个很长的文本,用于一个特别的短问题,而且甚至没有一个错误。但我总是想知道这是否是一种体面的方式,如果有更好的方式,我会怎么做。将memebers定义为asio对象的共享的想法是可以的。但您不应该每次都破坏和创建它们:
if (!m_resolver)
{
m_resolver.reset(...);
}
此外,如果确保asio对象上的所有操作都发生在运行io_服务的线程中(假设每个io_服务只有一个线程),则可以避免显式锁定。为此,只需分离接口函数的实现并使用post()。当然,使用shared_from_这个成语可以简化对象生命周期控制:
void CommandScreenshot::someMethod(Arg1 arg1, Arg2 arg2)
{
io_.post(bind(&CommandScreenshot::someMethodImpl, shared_from_this, arg1, arg2));
}
//...
void CommandScreenshot::someMethodImpl(Arg1 arg1, Arg2 arg2)
{
// do anything you want with m_resolver, m_socket etc.
}
void CommandScreenshot::someMethod(Arg1 arg1, Arg2 arg2)
{
io_.post(bind(&CommandScreenshot::someMethodImpl, shared_from_this, arg1, arg2));
}
//...
void CommandScreenshot::someMethodImpl(Arg1 arg1, Arg2 arg2)
{
// do anything you want with m_resolver, m_socket etc.
}