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 ····​asio:​:​post(io_service_,​35 ····​asio:​:​post(io_service_,​
38 ········boost:​:​bind(&chat_client:​:​do_write,​·this,​·​msg)​)​;​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 ········​})​;​
39 ··​}45 ··​}
40 46
41 ··​void·​close()​47 ··​void·​close()​
42 ··​{48 ··​{
43 ····​asio:​:​post(io_service_,​49 ····​asio:​:​post(io_service_,​·[this]()​·{·socket_.​close()​;​·})​;​
44 ········boost:​:​bind(&chat_client:​:​do_close,​·this)​)​;​
45 ··​}50 ··​}
46 51
47 private:​52 private:​
48 53 ··void·do_connect(tcp:​:​resolver:​:​iterator·endpoint_iterator)​
49 ··void·handle_connect(const·asio:​:​error_code&·error)​
50 ··{
51 ····if·(!error)​
52 ····{
53 ······asio:​:​async_read(socket_,​
54 ··········asio:​:​buffer(read_msg_.​data()​,​·chat_message:​:​header_length)​,​
55 ··········boost:​:​bind(&chat_client:​:​handle_read_header,​·this,​
56 ············asio:​:​placeholders:​:​error)​)​;​
57 ····}
58 ··}
59
60 ··void·handle_read_header(co​nst·asio:​:​error_code&·error)​
61 ··{
62 ····if·(!error·&&·read_msg_.​decode_header()​)​
63 ····{
64 ······asio:​:​async_read(socket_,​
65 ··········asio:​:​buffer(read_msg_.​body()​,​·read_msg_.​body_length()​)​,​
66 ··········boost:​:​bind(&chat_client:​:​handle_read_body,​·this,​
67 ············asio:​:​placeholders:​:​error)​)​;​
68 ····}
69 ····else
70 ····{
71 ······do_close()​;​
72 ····}
73 ··}
74
75 ··void·handle_read_body(cons​t·asio:​:​error_code&·error)​
76 ··{
77 ····if·(!error)​
78 ····{
79 ······std:​:​cout.​write(read_msg_.​body()​,​·read_msg_.​body_length()​)​;​
80 ······std:​:​cout·<<·"\n";​
81 ······asio:​:​async_read(socket_,​
82 ··········asio:​:​buffer(read_msg_.​data()​,​·chat_message:​:​header_length)​,​
83 ··········boost:​:​bind(&chat_client:​:​handle_read_header,​·this,​
84 ············asio:​:​placeholders:​:​error)​)​;​
85 ····}
86 ····else
87 ····{
88 ······do_close()​;​
89 ····}
90 ··}
91
92 ··void·do_write(chat_message​·msg)​
93 ··{
94 ····bool·write_in_progress·=·!write_msgs_.​empty()​;​
95 ····write_msgs_.​push_back(msg)​;​
96 ····if·(!write_in_progress)​
97 ····{
98 ······asio:​:​async_write(socket_,​
99 ··········asio:​:​buffer(write_msgs_.​front()​.​data()​,​
100 ············write_msgs_.​front()​.​length()​)​,​
101 ··········boost:​:​bind(&chat_client:​:​handle_write,​·this,​
102 ············asio:​:​placeholders:​:​error)​)​;​
103 ····}
104 ··}
105
106 ··void·handle_write(const·asio:​:​error_code&·error)​
107 ··​{54 ··​{
108 ····​if·(!error)​55 ····asio:​:​async_connect(socket_​,​·endpoint_iterator,​
109 ····{56 ········[this](std:​:​error_code·ec,​·tcp:​:​resolver:​:​iterator)​
110 ······write_msgs_.​pop_front()​;​57 ········{
111 ······if·(!write_msgs_.​empty()​)​58 ··········if·(!ec)​
112 ······​{59 ··········​{
113 ········asio:​:​async_write(socket_,​60 ············do_read_header()​;​
114 ············asio:​:​buffer(write_msgs_.​front()​.​data()​,​61 ··········}
115 ··············write_msgs_.​front()​.​length()​)​,​62 ········})​;​
116 ············boost:​:​bind(&chat_client:​:​handle_write,​·this,​63 ··}
117 ··············asio:​:​placeholders:​:​error)​)​;​64
118 ······}65 ··void·do_read_header()​
119 ····}66 ··{
120 ····​else67 ····asio:​:​async_read(socket_,​
121 ····{68 ········asio:​:​buffer(read_msg_.​data()​,​·chat_message:​:​header_length)​,​
122 ······​do_close()​;​69 ········[this](std:​:​error_code·ec,​·std:​:​size_t·/​*length*/​)​
123 ····}70 ········{
124 ··}71 ··········if·(!ec·&&·read_msg_.​decode_header()​)​
125 72 ··········{
126 ··void·​do_close()​73 ············​do_read_body()​;​
127 ··{74 ··········}
128 ····socket_.​close()​;​75 ··········else
76 ··········​{
77 ············​socket_.​close()​;​
78 ··········​}
79 ········​})​;​
80 ··​}
81
82 ··​void·​do_read_body()​
83 ··​{
84 ····​asio:​:​async_read(socket_,​
85 ········​asio:​:​buffer(read_msg_.​body()​,​·​read_msg_.​body_length()​)​,​
86 ········​[this](std:​:​error_code·​ec,​·​std:​:​size_t·​/​*length*/​)​
87 ········​{
88 ··········​if·​(!ec)​
89 ··········​{
90 ············​std:​:​cout.​write(read_msg_.​body()​,​·​read_msg_.​body_length()​)​;​
91 ············​std:​:​cout·​<<·​"\n";​
92 ············​do_read_header()​;​
93 ··········​}
94 ··········​else
95 ··········​{
96 ············​socket_.​close()​;​
97 ··········​}
98 ········​})​;​
99 ··​}
100
101 ··​void·​do_write()​
102 ··​{
103 ····​asio:​:​async_write(socket_,​
104 ········​asio:​:​buffer(write_msgs_.​front()​.​data()​,​
105 ··········​write_msgs_.​front()​.​length()​)​,​
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 ········​})​;​
129 ··​}121 ··​}
130 122
131 private:​123 private:​
132 ··​asio:​:​io_service&·​io_service_;​124 ··​asio:​:​io_service&·​io_service_;​
133 ··​tcp:​:​socket·​socket_;​125 ··​tcp:​:​socket·​socket_;​
134 ··​chat_message·​read_msg_;​126 ··​chat_message·​read_msg_;​
135 ··​chat_message_queue·​write_msgs_;​127 ··​chat_message_queue·​write_msgs_;​
136 };​128 };​
137 129
138 int·​main(int·​argc,​·​char*·​argv[])​130 int·​main(int·​argc,​·​char*·​argv[])​
139 {131 {
140 ··​try132 ··​try
141 ··​{133 ··​{
142 ····​if·​(argc·​!=·​3)​134 ····​if·​(argc·​!=·​3)​
143 ····​{135 ····​{
144 ······​std:​:​cerr·​<<·​"Usage:​·​chat_client·​<host>·​<port>\n";​136 ······​std:​:​cerr·​<<·​"Usage:​·​chat_client·​<host>·​<port>\n";​
145 ······​return·​1;​137 ······​return·​1;​
146 ····​}138 ····​}
147 139
148 ····​asio:​:​io_service·​io_service;​140 ····​asio:​:​io_service·​io_service;​
149 141
150 ····​tcp:​:​resolver·​resolver(io_service)​;​142 ····​tcp:​:​resolver·​resolver(io_service)​;​
151 ····​tcp:​:​resolver:​:​query·query(argv[1],​·​argv[2])​;​143 ····auto·endpoint_iterator·=·resolver.​resolve({·argv[1],​·​argv[2]·})​;​
152 ····tcp:​:​resolver:​:​iterator·iterator·=·resolver.​resolve(query)​;​144 ····​chat_client·c(io_service,​·​endpoint_iterator)​;​
153
154 ····chat_client·c(io_service,​·iterator)​;​
155 145
156 ····asio:​:​thread·​t(boost:​:​bind(&asio:​:​io_service:​:​run,​·&io_service)​)​;​146 ····​std:​:​thread·​t([&io_service]()​{·​io_service.​run()​;​·})​;​
157 147
158 ····​char·​line[chat_message:​:​max_body_length·​+·​1];​148 ····​char·​line[chat_message:​:​max_body_length·​+·​1];​
159 ····​while·​(std:​:​cin.​getline(line,​·​chat_message:​:​max_body_length·​+·​1)​)​149 ····​while·​(std:​:​cin.​getline(line,​·​chat_message:​:​max_body_length·​+·​1)​)​
160 ····​{150 ····​{
161 ······​using·​namespace·​std;​·​/​/​·​For·​strlen·​and·​memcpy.​
162 ······​chat_message·​msg;​151 ······​chat_message·​msg;​
163 ······​msg.​body_length(strlen(li​ne)​)​;​152 ······​msg.​body_length(std:​:​strlen(line)​)​;​
164 ······​memcpy(msg.​body()​,​·​line,​·​msg.​body_length()​)​;​153 ······std:​:​memcpy(msg.​body()​,​·​line,​·​msg.​body_length()​)​;​
165 ······​msg.​encode_header()​;​154 ······​msg.​encode_header()​;​
166 ······​c.​write(msg)​;​155 ······​c.​write(msg)​;​
167 ····​}156 ····​}
168 157
169 ····​c.​close()​;​158 ····​c.​close()​;​
170 ····​t.​join()​;​159 ····​t.​join()​;​
171 ··​}160 ··​}
172 ··​catch·​(std:​:​exception&·​e)​161 ··​catch·​(std:​:​exception&·​e)​
173 ··​{162 ··​{
174 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​163 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
175 ··​}164 ··​}
176 165
177 ··​return·​0;​166 ··​return·​0;​
178 }167 }