5 // Copyright (c) 2003-2016 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.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_service
& io_service
,
27 tcp::resolver::iterator endpoint_iterator
)
28 : io_service_(io_service
),
31 boost::asio::async_connect(socket_
, endpoint_iterator
,
32 boost::bind(&chat_client::handle_connect
, this,
33 boost::asio::placeholders::error
));
36 void write(const chat_message
& msg
)
38 io_service_
.post(boost::bind(&chat_client::do_write
, this, msg
));
43 io_service_
.post(boost::bind(&chat_client::do_close
, this));
48 void handle_connect(const boost::system::error_code
& error
)
52 boost::asio::async_read(socket_
,
53 boost::asio::buffer(read_msg_
.data(), chat_message::header_length
),
54 boost::bind(&chat_client::handle_read_header
, this,
55 boost::asio::placeholders::error
));
59 void handle_read_header(const boost::system::error_code
& error
)
61 if (!error
&& read_msg_
.decode_header())
63 boost::asio::async_read(socket_
,
64 boost::asio::buffer(read_msg_
.body(), read_msg_
.body_length()),
65 boost::bind(&chat_client::handle_read_body
, this,
66 boost::asio::placeholders::error
));
74 void handle_read_body(const boost::system::error_code
& error
)
78 std::cout
.write(read_msg_
.body(), read_msg_
.body_length());
80 boost::asio::async_read(socket_
,
81 boost::asio::buffer(read_msg_
.data(), chat_message::header_length
),
82 boost::bind(&chat_client::handle_read_header
, this,
83 boost::asio::placeholders::error
));
91 void do_write(chat_message msg
)
93 bool write_in_progress
= !write_msgs_
.empty();
94 write_msgs_
.push_back(msg
);
95 if (!write_in_progress
)
97 boost::asio::async_write(socket_
,
98 boost::asio::buffer(write_msgs_
.front().data(),
99 write_msgs_
.front().length()),
100 boost::bind(&chat_client::handle_write
, this,
101 boost::asio::placeholders::error
));
105 void handle_write(const boost::system::error_code
& error
)
109 write_msgs_
.pop_front();
110 if (!write_msgs_
.empty())
112 boost::asio::async_write(socket_
,
113 boost::asio::buffer(write_msgs_
.front().data(),
114 write_msgs_
.front().length()),
115 boost::bind(&chat_client::handle_write
, this,
116 boost::asio::placeholders::error
));
131 boost::asio::io_service
& io_service_
;
133 chat_message read_msg_
;
134 chat_message_queue write_msgs_
;
137 int main(int argc
, char* argv
[])
143 std::cerr
<< "Usage: chat_client <host> <port>\n";
147 boost::asio::io_service io_service
;
149 tcp::resolver
resolver(io_service
);
150 tcp::resolver::query
query(argv
[1], argv
[2]);
151 tcp::resolver::iterator iterator
= resolver
.resolve(query
);
153 chat_client
c(io_service
, iterator
);
155 boost::thread
t(boost::bind(&boost::asio::io_service::run
, &io_service
));
157 char line
[chat_message::max_body_length
+ 1];
158 while (std::cin
.getline(line
, chat_message::max_body_length
+ 1))
160 using namespace std
; // For strlen and memcpy.
162 msg
.body_length(strlen(line
));
163 memcpy(msg
.body(), line
, msg
.body_length());
171 catch (std::exception
& e
)
173 std::cerr
<< "Exception: " << e
.what() << "\n";