// // udp_server.cpp // ~~~~~~~~~~~~~~ // // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include #include #include #include #include #include #include #include "allocator.hpp" using boost::asio::ip::udp; #include class udp_server : boost::asio::coroutine { public: udp_server(boost::asio::io_context& io_context, unsigned short port, std::size_t buf_size) : socket_(io_context, udp::endpoint(udp::v4(), port)), buffer_(buf_size) { } void operator()(boost::system::error_code ec, std::size_t n = 0) { reenter (this) for (;;) { yield socket_.async_receive_from( boost::asio::buffer(buffer_), sender_, ref(this)); if (!ec) { for (std::size_t i = 0; i < n; ++i) buffer_[i] = ~buffer_[i]; socket_.send_to(boost::asio::buffer(buffer_, n), sender_, 0, ec); } } } friend void* asio_handler_allocate(std::size_t n, udp_server* s) { return s->allocator_.allocate(n); } friend void asio_handler_deallocate(void* p, std::size_t, udp_server* s) { s->allocator_.deallocate(p); } struct ref { explicit ref(udp_server* p) : p_(p) { } void operator()(boost::system::error_code ec, std::size_t n = 0) { (*p_)(ec, n); } private: udp_server* p_; friend void* asio_handler_allocate(std::size_t n, ref* r) { return asio_handler_allocate(n, r->p_); } friend void asio_handler_deallocate(void* p, std::size_t n, ref* r) { asio_handler_deallocate(p, n, r->p_); } }; private: udp::socket socket_; std::vector buffer_; udp::endpoint sender_; allocator allocator_; }; #include int main(int argc, char* argv[]) { if (argc != 5) { std::fprintf(stderr, "Usage: udp_server " " {spin|block}\n"); return 1; } unsigned short first_port = static_cast(std::atoi(argv[1])); unsigned short num_ports = static_cast(std::atoi(argv[2])); std::size_t buf_size = std::atoi(argv[3]); bool spin = (std::strcmp(argv[4], "spin") == 0); boost::asio::io_context io_context(1); std::vector > servers; for (unsigned short i = 0; i < num_ports; ++i) { unsigned short port = first_port + i; boost::shared_ptr s(new udp_server(io_context, port, buf_size)); servers.push_back(s); (*s)(boost::system::error_code()); } if (spin) for (;;) io_context.poll(); else io_context.run(); }