最近Boost.Asioのリファレンスを見ていて、async_acceptのオーバーロードが増えていることに気付きました: basic_socket_acceptor::async_accept – 1.66.0。
このページを見る限り、仮引数でbasic_socket<>を受け取らないものが加わっていたのです。もしかして、と思い確認するとやはりそうでした。内部でsocketを作ってacceptするらしく、コールバック関数などでaccept済みのソケットを受け取るというものになっています。
#include
#include
#include
#include
#include
using tcp = boost::asio::ip::tcp;
class Connection : public std::enable_shared_from_this
{
public:
static std::shared_ptr Run(tcp::socket&& s)
{
auto p = std::make_shared(std::move(s));
p->RunImpl();
return p;
}
Connection(tcp::socket&& s)
: m_socket(std::move(s))
{
}
~Connection() = default;
private:
void RunImpl()
{
boost::asio::async_write(m_socket, boost::asio::buffer(MESSAGE, std::strlen(MESSAGE)),
[self = shared_from_this()](boost::system::error_code ec, std::size_t)
{
if (ec)
{
std::cerr << "write error: " << ec << std::endl;
}
});
}
tcp::socket m_socket;
static inline constexpr const char MESSAGE[] = "OK";
Connection(Connection&&) = delete;
Connection(const Connection&) = delete;
Connection& operator=(Connection&&) = delete;
Connection& operator=(const Connection&) = delete;
};
class TcpServer
{
public:
TcpServer(boost::asio::io_context& context, tcp::endpoint endpoint)
: m_acceptor(context, endpoint)
{
}
void Run()
{
m_acceptor.async_accept([this](boost::system::error_code ec, tcp::socket s)
{
OnAccept(ec, std::move(s));
});
}
~TcpServer() = default;
private:
void OnAccept(boost::system::error_code ec, tcp::socket s)
{
if (ec)
{
std::cerr << "accept error: " << ec << std::endl;
}
else
{
Connection::Run(std::move(s));
}
Run();
}
tcp::acceptor m_acceptor;
TcpServer(TcpServer&&) = delete;
TcpServer(const TcpServer&) = delete;
TcpServer& operator=(TcpServer&&) = delete;
TcpServer& operator=(const TcpServer&) = delete;
};
int main()
{
boost::asio::io_context context;
TcpServer server(context, tcp::endpoint(tcp::v4(), 5000));
server.Run();
context.run();
std::quick_exit(0);
}
どうやら1.66.0から追加されたようです。Boost 1.66.0リリースノート - boostjpより:
basic_socket_acceptor::async_accept()
がソケットの参照をパラメータでとっていたが、ハンドラに渡されるよう変更。これはC++11以降でムーブサポートされている場合のみ使用できる
Boost.Asio公式のexampleも1.65と1.66とで変更が入っていました。見比べるとserverクラスのメンバー変数socket_が不要になったことが分かります。
地味ながら便利な変更点だと思います。
async_acceptにソケットを渡す必要がなくなっていた is a post from: イグトランスの頭の中