123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- //
- // 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 <boost/asio/io_context.hpp>
- #include <boost/asio/ip/udp.hpp>
- #include <boost/shared_ptr.hpp>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <vector>
- #include "allocator.hpp"
- using boost::asio::ip::udp;
- #include <boost/asio/yield.hpp>
- 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<unsigned char> buffer_;
- udp::endpoint sender_;
- allocator allocator_;
- };
- #include <boost/asio/unyield.hpp>
- int main(int argc, char* argv[])
- {
- if (argc != 5)
- {
- std::fprintf(stderr,
- "Usage: udp_server <port1> <nports> "
- "<bufsize> {spin|block}\n");
- return 1;
- }
- unsigned short first_port = static_cast<unsigned short>(std::atoi(argv[1]));
- unsigned short num_ports = static_cast<unsigned short>(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<boost::shared_ptr<udp_server> > servers;
- for (unsigned short i = 0; i < num_ports; ++i)
- {
- unsigned short port = first_port + i;
- boost::shared_ptr<udp_server> 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();
- }
|