我正在实现一个可以使用 tcp 和 unix 套接字的简单服务器后端。
这是监听器块:
static asio::awaitable<void> listener() {
const auto executor = co_await asio::this_coro::executor;
asio::local::stream_protocol::acceptor acceptor(executor, asio::local::stream_protocol::endpoint(socket_file_));
for (;;) {
auto socket = co_await acceptor.async_accept(asio::use_awaitable);
...
之后,会话将通过使用此
Session
创建socket
类的实例来初始化。
在这种情况下,
socket
的类型为 asio::local::stream_protocol::socket
,但在 tcp 情况下,类型将为 asio::ip::tcp::socket
.asio::basic_stream_socket
我想实现通用 Session
类:
template <typename Protocol, typename Executor>
class Session : public std::enable_shared_from_this<Session<Protocol, Executor>> {
using Socket = asio::basic_stream_socket<Protocol, Executor>;
public:
explicit Session(Socket sock) : socket_(std::move(sock)) {}
void start() {
...
在这种实现中,我必须在
Protocol
方法中明确指定类型 Executor
和 listener
:
std::make_shared<Session<asio::local::stream_protocol, asio::any_io_executor>>(std::move(socket))->start();
或
std::make_shared<Session<decltype(socket)::protocol_type, decltype(socket)::executor_type>>(std::move(socket))->start();
看起来很麻烦,看起来很多余。
有没有办法优化
Session
类模板定义?
作为免责声明,我对使用 boost asio 的异步会话一无所知。但是如果我正确理解你的问题,你想简化
shared_ptr
s 到你的 Session
类的创建,而不必写出复杂的模板参数。
一般来说,您可以使用模板化的自由工厂函数
create_session
来实现这一点,它可以从传递的参数中推断出它的模板参数,如下所示:
#include <memory>
//********************** my very own boost asio implementation **********************//
template <typename Protocol, typename Executor>
struct asio_basic_stream_socket{
using protocol_type = Protocol;
using executor_type = Executor;
};
template <typename Protocol, typename Executor>
struct asio_local_stream_protocol_socket : asio_basic_stream_socket<Protocol, Executor> {};
template <typename Protocol, typename Executor>
struct asio_ip_tcp_socket : asio_basic_stream_socket<Protocol, Executor> {};
//********************** Session **********************//
template <typename Protocol, typename Executor>
class Session //: std::enable_shared_from_this<Session>
{
public:
using Socket = asio_basic_stream_socket<Protocol, Executor>;
template <typename S>
friend auto create_session(S);
private:
Session(Socket){}
};
template <typename Socket>
auto create_session(Socket s)
{
using P = typename Socket::protocol_type;
using E = typename Socket::executor_type;
using S = Session<P,E>;
return std::shared_ptr<S>(new S(std::move(s)));
}
//********************** Usage **********************//
int main()
{
asio_local_stream_protocol_socket<int, bool> x;
auto session_ptr_x = create_session(x);
asio_ip_tcp_socket<std::string, double> y;
auto session_ptr_y = create_session(x);
}
一些注意事项:
create_session
的正文中还有一些模板混乱,但这被很好地隐藏起来了。Session
不需要从std::enable_shared_from_this
派生。Session
的构造函数是private的。这是基于 Session
实例只会通过工厂函数创建的假设。这当然不是必需的。