最近Boost.Asioのリファレンスを見ていて、async_acceptのオーバーロードが増えていることに気付きました: basic_socket_acceptor::async_accept – 1.66.0。
このページを見る限り、仮引数でbasic_socket<>を受け取らないものが加わっていたのです。もしかして、と思い確認するとやはりそうでした。内部でsocketを作ってacceptするらしく、コールバック関数などでaccept済みのソケットを受け取るというものになっています。
#include <cstdlib> #include <cstring> #include <iostream> #include <memory> #include <boost/asio.hpp> using tcp = boost::asio::ip::tcp; class Connection : public std::enable_shared_from_this<Connection> { public: static std::shared_ptr<Connection> Run(tcp::socket&& s) { auto p = std::make_shared<Connection>(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_が不要になったことが分かります。
地味ながら便利な変更点だと思います。
スポンサード リンク |
この記事のカテゴリ
- C++ ⇒ async_acceptにソケットを渡す必要がなくなっていた