如何在unix域和tcp套接字上设置接受器?

mwg9r5ms  于 5个月前  发布在  Unix
关注(0)|答案(1)|浏览(55)

我正在写一个服务器类,我希望能够支持任何流协议。
本页给出了一些提示:https://beta.boost.org/doc/libs/1_83_0/doc/html/boost_asio/overview/networking/other_protocols.html
然而,它在受体部分相当难以捉摸...
你有一个关于如何设置acceptorboost::asio::generic::stream_protocol::endpoint(至少可以是ip/TCP或unix域)一起工作的例子吗?

kognpnkq

kognpnkq1#

你需要有多个监听器,例如。

template <typename Socket> struct Listener {
    using Proto    = typename Socket::protocol_type;
    using Acceptor = asio::basic_socket_acceptor<Proto>;
    using Endpoint = Acceptor::endpoint_type;

    Listener(asio::any_io_executor ex, Endpoint ep) : acc_(std::move(ex), std::move(ep)) { accept_loop(); }

  private:
    void accept_loop() {
        acc_.async_accept([](error_code ec, Socket s) {
            std::cout << "Accepted (" << ec.message() << ") from " << s.remote_endpoint() << std::endl;
            if (!ec)
                std::make_shared<Session<Socket>>(std::move(s))->Start();
        });
    }
    Acceptor acc_;
};

字符串
正如你所看到的,session类也是在socket类型上模板化的,所以你只需要实现一次:

template <typename Socket> struct Session /*: BaseSession*/ {
    Session(Socket s) : sock_(std::move(s)) {}

    void Start() {
        read_loop();
    }

  private:
    void read_loop() {
        async_read_until(sock_, asio::dynamic_buffer(message), "\n",
                         [this, self = shared_from_this()](error_code ec, size_t n) {
                             std::cout << "Received (" << ec.message() << "): "              //
                                       << quoted(std::string_view(message).substr(0, n - 1)) //
                                       << std::endl;

                            if (!ec) {
                                message.erase(0, n);
                                read_loop();
                            }
                         });
    }
    std::string message;
    Socket sock_;
};


如果您需要对所有会话示例化进行通用操作,请考虑使用基类。
现在,多服务器就像这样简单:

struct MultiServer {
    MultiServer(asio::any_io_executor ex, std::set<uint16_t> tcp_listen_ports, std::set<std::string> unix_domain_socket) {
        for (auto p : tcp_listen_ports)
            listeners_.push_back(std::make_shared<Listener<tcp::socket>>(ex, tcp::endpoint{{}, p}));
        for (auto& s : unix_domain_socket)
            listeners_.push_back(std::make_shared<Listener<uxd::socket>>(ex, s));
    }

  private:
    std::vector<std::shared_ptr<void> > listeners_;
};

int main() {
    asio::io_context ioc;
    MultiServer      multi(ioc.get_executor(), {8989, 7979}, {"socket1", "socket2"});

    ioc.run_for(10s); // limited for Coliru
}


这会运行一个监听2个tcp端口和2个unix域套接字的服务器,并在所有端口上生成相同的会话:


的数据

完整列表

Live On Coliru

#include <boost/asio.hpp>
#include <iomanip>
#include <iostream>
#include <set>
namespace asio = boost::asio;
using namespace std::chrono_literals;
using boost::system::error_code;
using tcp = asio::ip::tcp;
using uxd = asio::local::stream_protocol;

struct BaseSession : std::enable_shared_from_this<BaseSession> {
    // in case you need any "common" behavior
    // virtual ~BaseSession() = default;
};

template <typename Socket> struct Session : BaseSession {
    Session(Socket s) : sock_(std::move(s)) {}

    void Start() {
        read_loop();
    }

  private:
    void read_loop() {
        async_read_until(sock_, asio::dynamic_buffer(message), "\n",
                         [this, self = shared_from_this()](error_code ec, size_t n) {
                             std::cout << "Received (" << ec.message() << "): "              //
                                       << quoted(std::string_view(message).substr(0, n - 1)) //
                                       << std::endl;

                            if (!ec) {
                                message.erase(0, n);
                                read_loop();
                            }
                         });
    }
    std::string message;
    Socket sock_;
};

template <typename Socket> struct Listener {
    using Proto    = typename Socket::protocol_type;
    using Acceptor = asio::basic_socket_acceptor<Proto>;
    using Endpoint = Acceptor::endpoint_type;

    Listener(asio::any_io_executor ex, Endpoint ep) : acc_(std::move(ex), std::move(ep)) { accept_loop(); }

  private:
    void accept_loop() {
        acc_.async_accept([](error_code ec, Socket s) {
            std::cout << "Accepted (" << ec.message() << ") from " << s.remote_endpoint() << std::endl;
            if (!ec)
                std::make_shared<Session<Socket>>(std::move(s))->Start();
        });
    }
    Acceptor acc_;
};

struct MultiServer {
    MultiServer(asio::any_io_executor ex, std::set<uint16_t> tcp_listen_ports, std::set<std::string> unix_domain_socket) {
        for (auto p : tcp_listen_ports)
            listeners_.push_back(std::make_shared<Listener<tcp::socket>>(ex, tcp::endpoint{{}, p}));
        for (auto& s : unix_domain_socket)
            listeners_.push_back(std::make_shared<Listener<uxd::socket>>(ex, s));
    }

  private:
    std::vector<std::shared_ptr<void> > listeners_;
};

int main() {
    asio::io_context ioc;
    MultiServer      multi(ioc.get_executor(), {8989, 7979}, {"socket1", "socket2"});

    ioc.run_for(10s); // limited for Coliru
}

相关问题