5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
14 #include <boost/bind/bind.hpp>
15 #include <boost/asio.hpp>
16 #include <boost/thread/thread.hpp>
17 #include "chat_message.hpp"
19 using boost::asio::ip::tcp
;
21 typedef std::deque
<chat_message
> chat_message_queue
;
26 chat_client(boost::asio::io_context
& io_context
,
27 const tcp::resolver::results_type
& endpoints
)
28 : io_context_(io_context
),
31 boost::asio::async_connect(socket_
, endpoints
,
32 boost::bind(&chat_client::handle_connect
, this,
33 boost::asio::placeholders::error
));
36 void write(const chat_message
& msg
)
38 boost::asio::post(io_context_
,
39 boost::bind(&chat_client::do_write
, this, msg
));
44 boost::asio::post(io_context_
,
45 boost::bind(&chat_client::do_close
, this));
50 void handle_connect(const boost::system::error_code
& error
)
54 boost::asio::async_read(socket_
,
55 boost::asio::buffer(read_msg_
.data(), chat_message::header_length
),
56 boost::bind(&chat_client::handle_read_header
, this,
57 boost::asio::placeholders::error
));
61 void handle_read_header(const boost::system::error_code
& error
)
63 if (!error
&& read_msg_
.decode_header())
65 boost::asio::async_read(socket_
,
66 boost::asio::buffer(read_msg_
.body(), read_msg_
.body_length()),
67 boost::bind(&chat_client::handle_read_body
, this,
68 boost::asio::placeholders::error
));
76 void handle_read_body(const boost::system::error_code
& error
)
80 std::cout
.write(read_msg_
.body(), read_msg_
.body_length());
82 boost::asio::async_read(socket_
,
83 boost::asio::buffer(read_msg_
.data(), chat_message::header_length
),
84 boost::bind(&chat_client::handle_read_header
, this,
85 boost::asio::placeholders::error
));
93 void do_write(chat_message msg
)
95 bool write_in_progress
= !write_msgs_
.empty();
96 write_msgs_
.push_back(msg
);
97 if (!write_in_progress
)
99 boost::asio::async_write(socket_
,
100 boost::asio::buffer(write_msgs_
.front().data(),
101 write_msgs_
.front().length()),
102 boost::bind(&chat_client::handle_write
, this,
103 boost::asio::placeholders::error
));
107 void handle_write(const boost::system::error_code
& error
)
111 write_msgs_
.pop_front();
112 if (!write_msgs_
.empty())
114 boost::asio::async_write(socket_
,
115 boost::asio::buffer(write_msgs_
.front().data(),
116 write_msgs_
.front().length()),
117 boost::bind(&chat_client::handle_write
, this,
118 boost::asio::placeholders::error
));
133 boost::asio::io_context
& io_context_
;
135 chat_message read_msg_
;
136 chat_message_queue write_msgs_
;
139 int main(int argc
, char* argv
[])
145 std::cerr
<< "Usage: chat_client <host> <port>\n";
149 boost::asio::io_context io_context
;
151 tcp::resolver
resolver(io_context
);
152 tcp::resolver::results_type endpoints
= resolver
.resolve(argv
[1], argv
[2]);
154 chat_client
c(io_context
, endpoints
);
156 boost::thread
t(boost::bind(&boost::asio::io_context::run
, &io_context
));
158 char line
[chat_message::max_body_length
+ 1];
159 while (std::cin
.getline(line
, chat_message::max_body_length
+ 1))
161 using namespace std
; // For strlen and memcpy.
163 msg
.body_length(strlen(line
));
164 memcpy(msg
.body(), line
, msg
.body_length());
172 catch (std::exception
& e
)
174 std::cerr
<< "Exception: " << e
.what() << "\n";