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 }