]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // async_tcp_echo_server.cpp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
b32b8144 FG |
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 | ||
11 | #include <cstdlib> | |
12 | #include <iostream> | |
13 | #include <memory> | |
14 | #include <utility> | |
15 | #include <boost/asio.hpp> | |
16 | ||
17 | using boost::asio::ip::tcp; | |
18 | ||
20effc67 TL |
19 | // Define a helper macro to invoke BOOST_ASIO_HANDLER_LOCATION with the current |
20 | // file name, line number, and function name. For the function name, you might | |
21 | // also consider using __PRETTY_FUNCTION__, BOOST_CURRENT_FUNCTION, or a hand- | |
22 | // crafted name. For C++20 or later, you may also use std::source_location. | |
23 | #define HANDLER_LOCATION \ | |
24 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__)) | |
25 | ||
b32b8144 FG |
26 | class session |
27 | : public std::enable_shared_from_this<session> | |
28 | { | |
29 | public: | |
30 | session(tcp::socket socket) | |
31 | : socket_(std::move(socket)) | |
32 | { | |
33 | } | |
34 | ||
35 | void start() | |
36 | { | |
20effc67 TL |
37 | HANDLER_LOCATION; |
38 | ||
b32b8144 FG |
39 | do_read(); |
40 | } | |
41 | ||
42 | private: | |
43 | void do_read() | |
44 | { | |
20effc67 TL |
45 | HANDLER_LOCATION; |
46 | ||
b32b8144 FG |
47 | auto self(shared_from_this()); |
48 | socket_.async_read_some(boost::asio::buffer(data_, max_length), | |
49 | [this, self](boost::system::error_code ec, std::size_t length) | |
50 | { | |
20effc67 TL |
51 | HANDLER_LOCATION; |
52 | ||
b32b8144 FG |
53 | if (!ec) |
54 | { | |
55 | do_write(length); | |
56 | } | |
57 | }); | |
58 | } | |
59 | ||
60 | void do_write(std::size_t length) | |
61 | { | |
20effc67 TL |
62 | HANDLER_LOCATION; |
63 | ||
b32b8144 FG |
64 | auto self(shared_from_this()); |
65 | boost::asio::async_write(socket_, boost::asio::buffer(data_, length), | |
66 | [this, self](boost::system::error_code ec, std::size_t /*length*/) | |
67 | { | |
20effc67 TL |
68 | HANDLER_LOCATION; |
69 | ||
b32b8144 FG |
70 | if (!ec) |
71 | { | |
72 | do_read(); | |
73 | } | |
74 | }); | |
75 | } | |
76 | ||
77 | tcp::socket socket_; | |
78 | enum { max_length = 1024 }; | |
79 | char data_[max_length]; | |
80 | }; | |
81 | ||
82 | class server | |
83 | { | |
84 | public: | |
85 | server(boost::asio::io_context& io_context, short port) | |
86 | : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) | |
87 | { | |
88 | do_accept(); | |
89 | } | |
90 | ||
91 | private: | |
92 | void do_accept() | |
93 | { | |
20effc67 TL |
94 | HANDLER_LOCATION; |
95 | ||
b32b8144 FG |
96 | acceptor_.async_accept( |
97 | [this](boost::system::error_code ec, tcp::socket socket) | |
98 | { | |
20effc67 TL |
99 | HANDLER_LOCATION; |
100 | ||
b32b8144 FG |
101 | if (!ec) |
102 | { | |
103 | std::make_shared<session>(std::move(socket))->start(); | |
104 | } | |
105 | ||
106 | do_accept(); | |
107 | }); | |
108 | } | |
109 | ||
110 | tcp::acceptor acceptor_; | |
111 | }; | |
112 | ||
113 | int main(int argc, char* argv[]) | |
114 | { | |
115 | try | |
116 | { | |
117 | if (argc != 2) | |
118 | { | |
119 | std::cerr << "Usage: async_tcp_echo_server <port>\n"; | |
120 | return 1; | |
121 | } | |
122 | ||
123 | boost::asio::io_context io_context; | |
124 | ||
125 | server s(io_context, std::atoi(argv[1])); | |
126 | ||
127 | io_context.run(); | |
128 | } | |
129 | catch (std::exception& e) | |
130 | { | |
131 | std::cerr << "Exception: " << e.what() << "\n"; | |
132 | } | |
133 | ||
134 | return 0; | |
135 | } |