tcp_server.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // tcp_server.cpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #include <boost/asio/io_context.hpp>
  11. #include <boost/asio/ip/tcp.hpp>
  12. #include <boost/asio/read.hpp>
  13. #include <boost/asio/write.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <cstdio>
  16. #include <cstdlib>
  17. #include <cstring>
  18. #include <vector>
  19. using boost::asio::ip::tcp;
  20. #include <boost/asio/yield.hpp>
  21. class tcp_server : boost::asio::coroutine
  22. {
  23. public:
  24. tcp_server(tcp::acceptor& acceptor, std::size_t buf_size) :
  25. acceptor_(acceptor),
  26. socket_(acceptor_.get_executor()),
  27. buffer_(buf_size)
  28. {
  29. }
  30. void operator()(boost::system::error_code ec, std::size_t n = 0)
  31. {
  32. reenter (this) for (;;)
  33. {
  34. yield acceptor_.async_accept(socket_, ref(this));
  35. while (!ec)
  36. {
  37. yield boost::asio::async_read(socket_,
  38. boost::asio::buffer(buffer_), ref(this));
  39. if (!ec)
  40. {
  41. for (std::size_t i = 0; i < n; ++i) buffer_[i] = ~buffer_[i];
  42. yield boost::asio::async_write(socket_,
  43. boost::asio::buffer(buffer_), ref(this));
  44. }
  45. }
  46. socket_.close();
  47. }
  48. }
  49. struct ref
  50. {
  51. explicit ref(tcp_server* p)
  52. : p_(p)
  53. {
  54. }
  55. void operator()(boost::system::error_code ec, std::size_t n = 0)
  56. {
  57. (*p_)(ec, n);
  58. }
  59. private:
  60. tcp_server* p_;
  61. };
  62. private:
  63. tcp::acceptor& acceptor_;
  64. tcp::socket socket_;
  65. std::vector<unsigned char> buffer_;
  66. tcp::endpoint sender_;
  67. };
  68. #include <boost/asio/unyield.hpp>
  69. int main(int argc, char* argv[])
  70. {
  71. if (argc != 5)
  72. {
  73. std::fprintf(stderr,
  74. "Usage: tcp_server <port> <nconns> "
  75. "<bufsize> {spin|block}\n");
  76. return 1;
  77. }
  78. unsigned short port = static_cast<unsigned short>(std::atoi(argv[1]));
  79. int max_connections = std::atoi(argv[2]);
  80. std::size_t buf_size = std::atoi(argv[3]);
  81. bool spin = (std::strcmp(argv[4], "spin") == 0);
  82. boost::asio::io_context io_context(1);
  83. tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));
  84. std::vector<boost::shared_ptr<tcp_server> > servers;
  85. for (int i = 0; i < max_connections; ++i)
  86. {
  87. boost::shared_ptr<tcp_server> s(new tcp_server(acceptor, buf_size));
  88. servers.push_back(s);
  89. (*s)(boost::system::error_code());
  90. }
  91. if (spin)
  92. for (;;) io_context.poll();
  93. else
  94. io_context.run();
  95. }