• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // reference_counted.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 
11 #include <boost/asio.hpp>
12 #include <iostream>
13 #include <memory>
14 #include <utility>
15 #include <vector>
16 #include <ctime>
17 
18 using boost::asio::ip::tcp;
19 
20 // A reference-counted non-modifiable buffer class.
21 class shared_const_buffer
22 {
23 public:
24   // Construct from a std::string.
shared_const_buffer(const std::string & data)25   explicit shared_const_buffer(const std::string& data)
26     : data_(new std::vector<char>(data.begin(), data.end())),
27       buffer_(boost::asio::buffer(*data_))
28   {
29   }
30 
31   // Implement the ConstBufferSequence requirements.
32   typedef boost::asio::const_buffer value_type;
33   typedef const boost::asio::const_buffer* const_iterator;
begin() const34   const boost::asio::const_buffer* begin() const { return &buffer_; }
end() const35   const boost::asio::const_buffer* end() const { return &buffer_ + 1; }
36 
37 private:
38   std::shared_ptr<std::vector<char> > data_;
39   boost::asio::const_buffer buffer_;
40 };
41 
42 class session
43   : public std::enable_shared_from_this<session>
44 {
45 public:
session(tcp::socket socket)46   session(tcp::socket socket)
47     : socket_(std::move(socket))
48   {
49   }
50 
start()51   void start()
52   {
53     do_write();
54   }
55 
56 private:
do_write()57   void do_write()
58   {
59     std::time_t now = std::time(0);
60     shared_const_buffer buffer(std::ctime(&now));
61 
62     auto self(shared_from_this());
63     boost::asio::async_write(socket_, buffer,
64         [self](boost::system::error_code /*ec*/, std::size_t /*length*/)
65         {
66         });
67   }
68 
69   // The socket used to communicate with the client.
70   tcp::socket socket_;
71 };
72 
73 class server
74 {
75 public:
server(boost::asio::io_context & io_context,short port)76   server(boost::asio::io_context& io_context, short port)
77     : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
78   {
79     do_accept();
80   }
81 
82 private:
do_accept()83   void do_accept()
84   {
85     acceptor_.async_accept(
86         [this](boost::system::error_code ec, tcp::socket socket)
87         {
88           if (!ec)
89           {
90             std::make_shared<session>(std::move(socket))->start();
91           }
92 
93           do_accept();
94         });
95   }
96 
97   tcp::acceptor acceptor_;
98 };
99 
main(int argc,char * argv[])100 int main(int argc, char* argv[])
101 {
102   try
103   {
104     if (argc != 2)
105     {
106       std::cerr << "Usage: reference_counted <port>\n";
107       return 1;
108     }
109 
110     boost::asio::io_context io_context;
111 
112     server s(io_context, std::atoi(argv[1]));
113 
114     io_context.run();
115   }
116   catch (std::exception& e)
117   {
118     std::cerr << "Exception: " << e.what() << "\n";
119   }
120 
121   return 0;
122 }
123