src/​examples/​cpp03/​chat/​chat_client.​cppsrc/​examples/​cpp11/​chat/​chat_client.​cpp
1 /​/​1 /​/​
2 /​/​·​chat_client.​cpp2 /​/​·​chat_client.​cpp
3 /​/​·​~~~~~~~~~~~~~~~3 /​/​·​~~~~~~~~~~~~~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2015·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2015·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​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)​8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​
9 /​/​9 /​/​
10 10
11 #include·​<cstdlib>11 #include·​<cstdlib>
12 #include·​<deque>12 #include·​<deque>
13 #include·​<iostream>13 #include·​<iostream>
14 #include·​<boost/​bind.​hpp>14 #include·​<thread>
15 #include·​"asio.​hpp"15 #include·​"asio.​hpp"
16 #include·​"chat_message.​hpp"16 #include·​"chat_message.​hpp"
17 17
18 using·​asio:​:​ip:​:​tcp;​18 using·​asio:​:​ip:​:​tcp;​
19 19
20 typedef·​std:​:​deque<chat_message>·​chat_message_queue;​20 typedef·​std:​:​deque<chat_message>·​chat_message_queue;​
21 21
22 class·​chat_client22 class·​chat_client
23 {23 {
24 public:​24 public:​
25 ··​chat_client(asio:​:​io_service&·​io_service,​25 ··​chat_client(asio:​:​io_service&·​io_service,​
26 ······​tcp:​:​resolver:​:​iterator·​endpoint_iterator)​26 ······​tcp:​:​resolver:​:​iterator·​endpoint_iterator)​
27 ····​:​·​io_service_(io_servic​e)​,​27 ····​:​·​io_service_(io_servic​e)​,​
28 ······​socket_(io_service)​28 ······​socket_(io_service)​
29 ··​{29 ··​{
30 ····asio:​:​async_connect(socket_​,​·endpoint_iterator,​30 ····do_connect(endpoint_i​terator)​;​
31 ········boost:​:​bind(&chat_client:​:​handle_connect,​·this,​
32 ··········asio:​:​placeholders:​:​error)​)​;​
33 ··​}31 ··​}
34 32
35 ··​void·​write(const·​chat_message&·​msg)​33 ··​void·​write(const·​chat_message&·​msg)​
36 ··​{34 ··​{
37 ····​io_service_.​post(boost:​:​bind(&chat_client:​:​do_write,​·this,​·msg)​)​;​35 ····​io_service_.​post(
36 ········​[this,​·​msg]()​
37 ········​{
38 ··········​bool·​write_in_progress·​=·​!write_msgs_.​empty()​;​
39 ··········​write_msgs_.​push_back(msg)​;​
40 ··········​if·​(!write_in_progress)​
41 ··········​{
42 ············​do_write()​;​
43 ··········​}
44 ········​})​;​
38 ··​}45 ··​}
39 46
40 ··​void·​close()​47 ··​void·​close()​
41 ··​{48 ··​{
42 ····​io_service_.​post(boost:​:​bind(&chat_client:​:​do_close,​·this)​)​;​49 ····​io_service_.​post([this]()​·{·socket_.​close()​;​·})​;​
43 ··​}50 ··​}
44 51
45 private:​52 private:​
46 53 ··void·do_connect(tcp:​:​resolver:​:​iterator·endpoint_iterator)​
47 ··void·handle_connect(const·asio:​:​error_code&·error)​
48 ··{
49 ····if·(!error)​
50 ····{
51 ······asio:​:​async_read(socket_,​
52 ··········asio:​:​buffer(read_msg_.​data()​,​·chat_message:​:​header_length)​,​
53 ··········boost:​:​bind(&chat_client:​:​handle_read_header,​·this,​
54 ············asio:​:​placeholders:​:​error)​)​;​
55 ····}
56 ··}
57
58 ··void·handle_read_header(co​nst·asio:​:​error_code&·error)​
59 ··{
60 ····if·(!error·&&·read_msg_.​decode_header()​)​
61 ····{
62 ······asio:​:​async_read(socket_,​
63 ··········asio:​:​buffer(read_msg_.​body()​,​·read_msg_.​body_length()​)​,​
64 ··········boost:​:​bind(&chat_client:​:​handle_read_body,​·this,​
65 ············asio:​:​placeholders:​:​error)​)​;​
66 ····}
67 ····else
68 ····{
69 ······do_close()​;​
70 ····}
71 ··}
72
73 ··void·handle_read_body(cons​t·asio:​:​error_code&·error)​
74 ··​{54 ··​{
75 ····​if·(!error)​55 ····asio:​:​async_connect(socket_​,​·endpoint_iterator,​
76 ····{56 ········[this](std:​:​error_code·ec,​·tcp:​:​resolver:​:​iterator)​
77 ······std:​:​cout.​write(read_msg_.​body()​,​·read_msg_.​body_length()​)​;​57 ········{
78 ······std:​:​cout·<<·"\n";​58 ··········if·(!ec)​
79 ······asio:​:​async_read(socket_,​59 ··········{
80 ··········asio:​:​buffer(read_msg_.​data()​,​·chat_message:​:​header_length)​,​60 ············do_read_header()​;​
81 ··········boost:​:​bind(&chat_client:​:​handle_read_header,​·this,​61 ··········}
82 ············asio:​:​placeholders:​:​error)​)​;​62 ········})​;​
83 ····​}63 ··​}
84 ····else64
85 ····{65 ··void·do_read_header()​
86 ······do_close()​;​66 ··{
87 ····}67 ····asio:​:​async_read(socket_,​
88 ··}68 ········asio:​:​buffer(read_msg_.​data()​,​·chat_message:​:​header_length)​,​
89 69 ········[this](std:​:​error_code·ec,​·std:​:​size_t·/​*length*/​)​
90 ··void·do_write(chat_message​·msg)​70 ········{
91 ··{71 ··········if·(!ec·&&·read_msg_.​decode_header()​)​
92 ····bool·write_in_progress·=·!write_msgs_.​empty()​;​72 ··········{
93 ····write_msgs_.​push_back(msg)​;​73 ············do_read_body()​;​
94 ····if·(!write_in_progress)​74 ··········}
95 ····{75 ··········else
96 ······asio:​:​async_write(socket_,​76 ··········{
97 ··········asio:​:​buffer(write_msgs_.​front()​.​data()​,​77 ············socket_.​close()​;​
98 ············write_msgs_.​front()​.​length()​)​,​78 ··········}
99 ··········boost:​:​bind(&chat_client:​:​handle_write,​·this,​79 ········})​;​
100 ············asio:​:​placeholders:​:​error)​)​;​80 ··}
101 ····}81
102 ··}82 ··void·do_read_body()​
103 83 ··{
104 ··void·handle_write(const·​asio:​:​error_code&·error)​84 ····​asio:​:​async_read(socket_,​
105 ··{85 ········asio:​:​buffer(read_msg_.​body()​,​·read_msg_.​body_length()​)​,​
106 ····​if·(!error)​86 ········[this](std:​:​error_code·ec,​·std:​:​size_t·/​*length*/​)​
107 ····​{87 ········​{
108 ······write_msgs_.​pop_front()​;​88 ··········if·(!ec)​
109 ······if·(!write_msgs_.​empty()​)​89 ··········{
110 ······{90 ············std:​:​cout.​write(read_msg_.​body()​,​·read_msg_.​body_length()​)​;​
111 ········asio:​:​async_write(socket_,​91 ············std:​:​cout·<<·"\n";​
112 ············asio:​:​buffer(write_msgs_.​front()​.​data()​,​92 ············do_read_header()​;​
113 ··············write_msgs_.​front()​.​length()​)​,​93 ··········}
114 ············boost:​:​bind(&chat_client:​:​handle_write,​·this,​94 ··········​else
115 ··············asio:​:​placeholders:​:​error)​)​;​95 ··········{
116 ······}96 ············socket_.​close()​;​
117 ····​}97 ··········​}
118 ····else98 ········})​;​
119 ····{99 ··}
120 ······do_close()​;​100
121 ····}101 ··void·do_write()​
122 ··}102 ··{
123 103 ····asio:​:​async_write(socket_,​
124 ··void·do_close()​104 ········asio:​:​buffer(write_msgs_.​front()​.​data()​,​
125 ··{105 ··········write_msgs_.​front()​.​length()​)​,​
126 ····​socket_.​close()​;​106 ········[this](std:​:​error_code·ec,​·std:​:​size_t·/​*length*/​)​
107 ········​{
108 ··········​if·​(!ec)​
109 ··········​{
110 ············​write_msgs_.​pop_front()​;​
111 ············​if·​(!write_msgs_.​empty()​)​
112 ············​{
113 ··············​do_write()​;​
114 ············​}
115 ··········​}
116 ··········​else
117 ··········​{
118 ············​socket_.​close()​;​
119 ··········​}
120 ········​})​;​
127 ··​}121 ··​}
128 122
129 private:​123 private:​
130 ··​asio:​:​io_service&·​io_service_;​124 ··​asio:​:​io_service&·​io_service_;​
131 ··​tcp:​:​socket·​socket_;​125 ··​tcp:​:​socket·​socket_;​
132 ··​chat_message·​read_msg_;​126 ··​chat_message·​read_msg_;​
133 ··​chat_message_queue·​write_msgs_;​127 ··​chat_message_queue·​write_msgs_;​
134 };​128 };​
135 129
136 int·​main(int·​argc,​·​char*·​argv[])​130 int·​main(int·​argc,​·​char*·​argv[])​
137 {131 {
138 ··​try132 ··​try
139 ··​{133 ··​{
140 ····​if·​(argc·​!=·​3)​134 ····​if·​(argc·​!=·​3)​
141 ····​{135 ····​{
142 ······​std:​:​cerr·​<<·​"Usage:​·​chat_client·​<host>·​<port>\n";​136 ······​std:​:​cerr·​<<·​"Usage:​·​chat_client·​<host>·​<port>\n";​
143 ······​return·​1;​137 ······​return·​1;​
144 ····​}138 ····​}
145 139
146 ····​asio:​:​io_service·​io_service;​140 ····​asio:​:​io_service·​io_service;​
147 141
148 ····​tcp:​:​resolver·​resolver(io_service)​;​142 ····​tcp:​:​resolver·​resolver(io_service)​;​
149 ····​tcp:​:​resolver:​:​query·query(argv[1],​·​argv[2])​;​143 ····auto·endpoint_iterator·=·resolver.​resolve({·argv[1],​·​argv[2]·})​;​
150 ····tcp:​:​resolver:​:​iterator·iterator·=·resolver.​resolve(query)​;​144 ····​chat_client·c(io_service,​·​endpoint_iterator)​;​
151
152 ····chat_client·c(io_service,​·iterator)​;​
153 145
154 ····asio:​:​thread·​t(boost:​:​bind(&asio:​:​io_service:​:​run,​·&io_service)​)​;​146 ····​std:​:​thread·​t([&io_service]()​{·​io_service.​run()​;​·})​;​
155 147
156 ····​char·​line[chat_message:​:​max_body_length·​+·​1];​148 ····​char·​line[chat_message:​:​max_body_length·​+·​1];​
157 ····​while·​(std:​:​cin.​getline(line,​·​chat_message:​:​max_body_length·​+·​1)​)​149 ····​while·​(std:​:​cin.​getline(line,​·​chat_message:​:​max_body_length·​+·​1)​)​
158 ····​{150 ····​{
159 ······​using·​namespace·​std;​·​/​/​·​For·​strlen·​and·​memcpy.​
160 ······​chat_message·​msg;​151 ······​chat_message·​msg;​
161 ······​msg.​body_length(strlen(li​ne)​)​;​152 ······​msg.​body_length(std:​:​strlen(line)​)​;​
162 ······​memcpy(msg.​body()​,​·​line,​·​msg.​body_length()​)​;​153 ······std:​:​memcpy(msg.​body()​,​·​line,​·​msg.​body_length()​)​;​
163 ······​msg.​encode_header()​;​154 ······​msg.​encode_header()​;​
164 ······​c.​write(msg)​;​155 ······​c.​write(msg)​;​
165 ····​}156 ····​}
166 157
167 ····​c.​close()​;​158 ····​c.​close()​;​
168 ····​t.​join()​;​159 ····​t.​join()​;​
169 ··​}160 ··​}
170 ··​catch·​(std:​:​exception&·​e)​161 ··​catch·​(std:​:​exception&·​e)​
171 ··​{162 ··​{
172 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​163 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
173 ··​}164 ··​}
174 165
175 ··​return·​0;​166 ··​return·​0;​
176 }167 }