adapted_echo_server.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //
  2. // Copyright (c) 2011 Thomas Heller
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #include <cstdlib>
  8. #include <iostream>
  9. #define BOOST_PHOENIX_NO_PREDEFINED_TERMINALS
  10. #include <boost/phoenix.hpp>
  11. #include <boost/asio.hpp>
  12. namespace phx = boost::phoenix;
  13. using boost::phoenix::ref;
  14. BOOST_PHOENIX_ADAPT_FUNCTION(void, read, boost::asio::async_read, 4)
  15. BOOST_PHOENIX_ADAPT_FUNCTION(void, write, boost::asio::async_write, 3)
  16. BOOST_PHOENIX_ADAPT_FUNCTION(boost::asio::mutable_buffers_1, buffer, boost::asio::buffer, 2)
  17. template <typename Acceptor, typename Socket, typename Handler>
  18. void accept_impl(Acceptor & acceptor, Socket & socket, Handler const & handler)
  19. {
  20. acceptor.async_accept(socket, handler);
  21. }
  22. BOOST_PHOENIX_ADAPT_FUNCTION(void, accept, accept_impl, 3)
  23. typedef phx::expression::local_variable<struct action_key>::type action;
  24. #include <boost/function.hpp>
  25. int main(int argc, char* argv[])
  26. {
  27. try
  28. {
  29. if (argc != 2)
  30. {
  31. std::cerr << "Usage: async_tcp_echo_server <port>\n";
  32. return 1;
  33. }
  34. phx::lambda_type lambda;
  35. phx::arg_names::_1_type _1;
  36. boost::asio::io_service io_service;
  37. boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), std::atoi(argv[1])));
  38. boost::asio::ip::tcp::socket socket(io_service);
  39. std::size_t const max_length = 1024;
  40. char buf[max_length];
  41. std::cout << "server starting...\n";
  42. boost::function<void(boost::system::error_code const &)> accept_handler;
  43. phx::expression::argument<1>::type _error;
  44. phx::expression::argument<2>::type _length;
  45. action _action;
  46. BOOST_AUTO(
  47. create_handler
  48. , (lambda(_action = lambda[_1])
  49. [
  50. if_(!_error)
  51. [
  52. bind(_action, ref(socket), ref(buf), _error, _length)
  53. ]
  54. .else_
  55. [
  56. bind(&boost::asio::ip::tcp::socket::close, ref(socket))
  57. , accept(ref(acceptor), ref(socket), phx::ref(accept_handler))
  58. ]
  59. ])
  60. );
  61. boost::function<void(boost::system::error_code const &, std::size_t)> read_handler;
  62. boost::function<void(boost::system::error_code const &, std::size_t)> write_handler;
  63. accept_handler =
  64. if_(!_error)
  65. [
  66. read(ref(socket), buffer(ref(buf), max_length), boost::asio::transfer_at_least(1), phx::ref(read_handler))
  67. ];
  68. {
  69. phx::expression::argument<1>::type _socket;
  70. phx::expression::argument<2>::type _buf;
  71. phx::expression::argument<3>::type _error;
  72. phx::expression::argument<4>::type _length;
  73. read_handler = create_handler(
  74. write(_socket, buffer(_buf, _length), phx::ref(write_handler))
  75. );
  76. write_handler = create_handler(
  77. read(_socket, buffer(_buf, max_length), boost::asio::transfer_at_least(1), phx::ref(read_handler))
  78. );
  79. }
  80. acceptor.async_accept(
  81. socket
  82. , accept_handler
  83. );
  84. io_service.run();
  85. }
  86. catch (std::exception& e)
  87. {
  88. std::cerr << "Exception: " << e.what() << "\n";
  89. }
  90. return 0;
  91. }