| // |
| // Copyright (c) 2011 Thomas Heller |
| // |
| // 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 <cstdlib> |
| #include <iostream> |
| |
| #define BOOST_PHOENIX_NO_PREDEFINED_TERMINALS |
| |
| #include <boost/phoenix.hpp> |
| #include <boost/asio.hpp> |
| |
| namespace phx = boost::phoenix; |
| |
| using boost::phoenix::ref; |
| |
| BOOST_PHOENIX_ADAPT_FUNCTION(void, read, boost::asio::async_read, 4) |
| BOOST_PHOENIX_ADAPT_FUNCTION(void, write, boost::asio::async_write, 3) |
| BOOST_PHOENIX_ADAPT_FUNCTION(boost::asio::mutable_buffers_1, buffer, boost::asio::buffer, 2) |
| |
| template <typename Acceptor, typename Socket, typename Handler> |
| void accept_impl(Acceptor & acceptor, Socket & socket, Handler const & handler) |
| { |
| acceptor.async_accept(socket, handler); |
| } |
| BOOST_PHOENIX_ADAPT_FUNCTION(void, accept, accept_impl, 3) |
| |
| typedef phx::expression::local_variable<struct action_key>::type action; |
| |
| #include <boost/function.hpp> |
| |
| int main(int argc, char* argv[]) |
| { |
| try |
| { |
| if (argc != 2) |
| { |
| std::cerr << "Usage: async_tcp_echo_server <port>\n"; |
| return 1; |
| } |
| |
| phx::lambda_type lambda; |
| phx::arg_names::_1_type _1; |
| |
| boost::asio::io_service io_service; |
| boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), std::atoi(argv[1]))); |
| boost::asio::ip::tcp::socket socket(io_service); |
| std::size_t const max_length = 1024; |
| char buf[max_length]; |
| |
| std::cout << "server starting...\n"; |
| |
| boost::function<void(boost::system::error_code const &)> accept_handler; |
| phx::expression::argument<1>::type _error; |
| phx::expression::argument<2>::type _length; |
| action _action; |
| BOOST_AUTO( |
| create_handler |
| , (lambda(_action = lambda[_1]) |
| [ |
| if_(!_error) |
| [ |
| bind(_action, ref(socket), ref(buf), _error, _length) |
| ] |
| .else_ |
| [ |
| bind(&boost::asio::ip::tcp::socket::close, ref(socket)) |
| , accept(ref(acceptor), ref(socket), phx::ref(accept_handler)) |
| ] |
| ]) |
| ); |
| boost::function<void(boost::system::error_code const &, std::size_t)> read_handler; |
| boost::function<void(boost::system::error_code const &, std::size_t)> write_handler; |
| |
| accept_handler = |
| if_(!_error) |
| [ |
| read(ref(socket), buffer(ref(buf), max_length), boost::asio::transfer_at_least(1), phx::ref(read_handler)) |
| ]; |
| |
| { |
| phx::expression::argument<1>::type _socket; |
| phx::expression::argument<2>::type _buf; |
| phx::expression::argument<3>::type _error; |
| phx::expression::argument<4>::type _length; |
| read_handler = create_handler( |
| write(_socket, buffer(_buf, _length), phx::ref(write_handler)) |
| ); |
| |
| write_handler = create_handler( |
| read(_socket, buffer(_buf, max_length), boost::asio::transfer_at_least(1), phx::ref(read_handler)) |
| ); |
| } |
| |
| acceptor.async_accept( |
| socket |
| , accept_handler |
| ); |
| |
| io_service.run(); |
| } |
| catch (std::exception& e) |
| { |
| std::cerr << "Exception: " << e.what() << "\n"; |
| } |
| |
| return 0; |
| } |