Я создаю серверное приложение на С++ 11 с помощью Boost.Asio. Я создал класс Server
, который заботится о принятии новых соединений. Это в основном просто:
void Server::Accept() {
socket_.reset(new boost::asio::ip::tcp::socket(*io_service_));
acceptor_.async_accept(*socket_,
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
}
void Server::HandleAccept(const boost::system::error_code& error) {
if (!error) {
// TODO
} else {
TRACE_ERROR("Server::HandleAccept: Error!");
}
Accept();
}
Я нашел два способа (я уверен, что их больше), чтобы "исправить" комментарий TODO
, т.е. переместить сокет туда, куда он должен идти. В моем случае я просто хочу вернуться к экземпляру класса, которому принадлежит экземпляр Server
(который затем переносит его в класс Connection
и вставляет его в список).
-
Server
имеет параметр в своем конструкторе:std::function<void(socket)> OnAccept
, который вызывается вHandleAccept
. - Я создаю абстрактный класс
IServerHandler
или что угодно, у которого есть один виртуальный методOnAccept
.Server
принимаетIServerHandler
как параметр в своем конструкторе, а экземпляр класса, владеющий экземпляром сервера, расширяетIServerHandler
и строитServer
с параметром*this
.
Каковы плюсы и минусы варианта 1 по сравнению с вариантом 2? Есть ли лучшие варианты? У меня такая же проблема в классе Connection
(OnConnectionClosed
). Кроме того, в зависимости от того, как я решаю создать систему, может потребоваться обратный вызов OnPacketReceived
и OnPacketSent
.