通过CRTP或PBCP或鸭子打字来增强ASIO
Boost ASIO with CRTP or PBCP or duck-typing
我想为tcp客户端/服务器实现在boost ASIO上编写一个包装器。boost ASIO的接口确实很好,但必须包装的原因是能够用其他东西替换事件循环。在我们的用例中,我们只需要为每个异步读取调用相同的处理程序函数,应用程序不需要为每个asyncRead调用传递处理程序。因此,注册一次处理程序会有所帮助。我试过的一种方法是这样的——
template <class Connection>
struct TCPClient { // implements the interface with ASIO
Connection *_connection;
void setConnection (Connection *connection)
{
_connection = connection;
}
void asyncRead ()
{
_socket.async_read_some(boost::asio::null_buffers(),
[this] (ErrorType err, unsigned a) {
if (_connection) _connection->handleRead(err);
if (!err) asyncRead();
});
}
};
我可以用CRTP 做类似的事情
class MyConnection : public TCPClient<MyConnection> {
void readHandler (TCPClient::ErrType err)
{
}
};
在TCPClient类中,asyncRead将是
void asyncRead ()
{
_socket.async_read_some(boost::asio::null_buffers(),
[this] (ErrorType err, unsigned a) {
((Connection *)this)->handleRead(err);
if (!err) asyncRead();
});
}
这种情况很有帮助,因为TCPClient和连接的生存期是相同的。
或PBCP
template <typename Connection>
class TCPClient : public Connection {
void asyncRead ()
{
_socket.async_read_some(boost::asio::null_buffers(),
[this] (ErrorType err, unsigned a) {
Connection::handleRead(err);
if (!err) asyncRead();
});
}
};
我不认为实际上有一个is-a关系b/w TCPCLient和Connection。我不知道这些方案中是否有一个是好的。(我还想知道为什么ASIO没有一个is缓存一次处理程序并每次调用它的方案。至少在异步读取的情况下,通常不会返回上下文。在我们的情况中,读取消息的速率是最大的问题,Boost ASIO每次复制读取处理程序+存储内存分配真的很糟糕。因此,根据测试结果,我们可能不得不将事件循环更改为自定义)
我在这个意义上做了一些工作。在您的CRTP基类中,您可以尝试创建一个模板参数化方法,该方法调用派生类并设置一个std::函数,该函数包含一个需要传递给async_read/write的lamba。
基本类别:
template <class Connection>
struct TCPClient { // implements the interface with ASIO
std::function<void(const boost::system::error&) handler{};
void registerConnectionHandler(std::function<void(const boost::system::error&)> &&impl)
{
static_cast<MyConnection*>(this)->registerConnectionHandler(std::forward<decltype(impl)>(impl));
}
void asyncRead ()
{
_socket.async_read_some(boost::asio::null_buffers(), handler);
}
};
在派生类中:
class MyConnection : public TCPClient<MyConnection> {
public:
void registerConnectionHandler(std::function<void(const boost::system::error&)> &&impl)
{
handler = std::move(impl);
}
};
另一种方法是在派生类中实现处理程序,而不使用带有std::函数的registerConnectionHandler,这可能是最好的方法:
class MyConnection : public TCPClient<MyConnection> {
public:
void registerConnectionHandler()
{
handler = [this](const boost::system::error &err)
{
// your stuff here
};
}
};
相关文章:
- 理解boost::asio-async_read在无需读取内容时的行为
- 提升 ASIO 无法识别计时器对象
- 无法将结构注册为增强几何体3D点
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- 增强 ASIO 和串行端口异步读取
- 增强 ASIO 阻止回调
- 通过CRTP或PBCP或鸭子打字来增强ASIO
- 增强ASIO和线程之间的消息传递
- 增强ASIO绑定端点
- 增强ASIO TCP套接字可用报告不正确的字节数
- 增强所有(或多个)端口上的 Asio UDP 侦听
- C++增强了asio多线程
- 增强asio网络独立发送和接收
- 在不关闭连接的情况下,在循环中增强asio加密
- 增强asio客户端身份验证
- 什么处理程序增强.Asio在幕后执行
- 通过代理服务器增强asio套接字连接
- 增强ASIO TCP消息分离
- 增强asio缓冲区延迟分配