• 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 <boost/bind/bind.hpp>
13 #include <boost/enable_shared_from_this.hpp>
14 #include <boost/shared_ptr.hpp>
15 #include <iostream>
16 #include <vector>
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   boost::shared_ptr<std::vector<char> > data_;
39   boost::asio::const_buffer buffer_;
40 };
41 
42 class session
43   : public boost::enable_shared_from_this<session>
44 {
45 public:
session(boost::asio::io_context & io_context)46   session(boost::asio::io_context& io_context)
47     : socket_(io_context)
48   {
49   }
50 
socket()51   tcp::socket& socket()
52   {
53     return socket_;
54   }
55 
start()56   void start()
57   {
58     using namespace std; // For time_t, time and ctime.
59     time_t now = time(0);
60     shared_const_buffer buffer(ctime(&now));
61     boost::asio::async_write(socket_, buffer,
62         boost::bind(&session::handle_write, shared_from_this()));
63   }
64 
handle_write()65   void handle_write()
66   {
67   }
68 
69 private:
70   // The socket used to communicate with the client.
71   tcp::socket socket_;
72 };
73 
74 typedef boost::shared_ptr<session> session_ptr;
75 
76 class server
77 {
78 public:
server(boost::asio::io_context & io_context,short port)79   server(boost::asio::io_context& io_context, short port)
80     : io_context_(io_context),
81       acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
82   {
83     session_ptr new_session(new session(io_context_));
84     acceptor_.async_accept(new_session->socket(),
85         boost::bind(&server::handle_accept, this, new_session,
86           boost::asio::placeholders::error));
87   }
88 
handle_accept(session_ptr new_session,const boost::system::error_code & error)89   void handle_accept(session_ptr new_session,
90       const boost::system::error_code& error)
91   {
92     if (!error)
93     {
94       new_session->start();
95     }
96 
97     new_session.reset(new session(io_context_));
98     acceptor_.async_accept(new_session->socket(),
99         boost::bind(&server::handle_accept, this, new_session,
100           boost::asio::placeholders::error));
101   }
102 
103 private:
104   boost::asio::io_context& io_context_;
105   tcp::acceptor acceptor_;
106 };
107 
main(int argc,char * argv[])108 int main(int argc, char* argv[])
109 {
110   try
111   {
112     if (argc != 2)
113     {
114       std::cerr << "Usage: reference_counted <port>\n";
115       return 1;
116     }
117 
118     boost::asio::io_context io_context;
119 
120     using namespace std; // For atoi.
121     server s(io_context, atoi(argv[1]));
122 
123     io_context.run();
124   }
125   catch (std::exception& e)
126   {
127     std::cerr << "Exception: " << e.what() << "\n";
128   }
129 
130   return 0;
131 }
132