• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//
2// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8/**
9\page tutdaytime1 Daytime.1 - A synchronous TCP daytime client
10
11This tutorial program shows how to use asio to implement a client application
12with TCP.
13
14\dontinclude daytime1/client.cpp
15\skip #include
16
17We start by including the necessary header files.
18
19\until asio.hpp
20
21The purpose of this application is to access a daytime service,
22so we need the user to specify the server.
23
24\until }
25
26All programs that use asio need to have at least one I/O execution context,
27such as an boost::asio::io_context object.
28
29\until boost::asio::io_context
30
31We need to turn the server name that was specified as a parameter to the
32application, into a TCP endpoint. To do this we use an
33boost::asio::ip::tcp::resolver object.
34
35\until tcp::resolver
36
37A resolver takes a host name and service name and turns them into a list of
38endpoints. We perform a resolve call using the name of the server, specified in
39<tt>argv[1]</tt>, and the name of the service, in this case <tt>"daytime"</tt>.
40
41The list of endpoints is returned using an object of type
42boost::asio::ip::tcp::resolver::results_type. This object is a range, with begin() and
43end() member functions that may be used for iterating over the results.
44
45\until resolver.resolve
46
47Now we create and connect the socket. The list of endpoints obtained above may
48contain both IPv4 and IPv6 endpoints, so we need to try each of them until we
49find one that works. This keeps the client program independent of a specific IP
50version. The boost::asio::connect() function does this for us automatically.
51
52\until boost::asio::connect
53
54The connection is open. All we need to do now is read the response from the
55daytime service.
56
57We use a <tt>boost::array</tt> to hold the received data. The boost::asio::buffer()
58function automatically determines the size of the array to help prevent buffer
59overruns. Instead of a <tt>boost::array</tt>, we could have used a <tt>char
60[]</tt> or <tt>std::vector</tt>.
61
62\until read_some
63
64When the server closes the connection, the boost::asio::ip::tcp::socket::read_some()
65function will exit with the boost::asio::error::eof error, which is how we know to
66exit the loop.
67
68\until }
69
70Finally, handle any exceptions that may have been thrown.
71
72\until }
73\until }
74
75See the \ref tutdaytime1src "full source listing" \n
76Return to the \ref index "tutorial index" \n
77Next: \ref tutdaytime2
78
79*/
80
81/**
82\page tutdaytime1src Source listing for Daytime.1
83\include daytime1/client.cpp
84Return to \ref tutdaytime1
85*/
86
87/**
88\page tutdaytime2 Daytime.2 - A synchronous TCP daytime server
89
90This tutorial program shows how to use asio to implement a server application
91with TCP.
92
93\dontinclude daytime2/server.cpp
94\skip #include
95
96\until using
97
98We define the function <tt>make_daytime_string()</tt> to create the string to
99be sent back to the client. This function will be reused in all of our daytime
100server applications.
101
102\until boost::asio::io_context
103
104A boost::asio::ip::tcp::acceptor object needs to be created to listen
105for new connections. It is initialised to listen on TCP port 13, for IP version 4.
106
107\until tcp::acceptor
108
109This is an iterative server, which means that it will handle one
110connection at a time. Create a socket that will represent the connection to the
111client, and then wait for a connection.
112
113\until acceptor.accept
114
115A client is accessing our service. Determine the current time
116and transfer this information to the client.
117
118\until }
119\until }
120
121Finally, handle any exceptions.
122
123\until }
124\until }
125
126See the \ref tutdaytime2src "full source listing" \n
127Return to the \ref index "tutorial index" \n
128Previous: \ref tutdaytime1 \n
129Next: \ref tutdaytime3
130
131*/
132
133/**
134\page tutdaytime2src Source listing for Daytime.2
135\include daytime2/server.cpp
136Return to \ref tutdaytime2
137*/
138
139/**
140\page tutdaytime3 Daytime.3 - An asynchronous TCP daytime server
141
142\section tutdaytime3funcmain The main() function
143
144\dontinclude daytime3/server.cpp
145\skip int main()
146\until try
147\until {
148
149We need to create a server object to accept incoming client connections. The
150boost::asio::io_context object provides I/O services, such as sockets, that the
151server object will use.
152
153\until tcp_server
154
155Run the boost::asio::io_context object so that it will perform asynchronous operations
156on your behalf.
157
158\until return 0;
159\until }
160
161\section tutdaytime3classtcp_server The tcp_server class
162
163\dontinclude daytime3/server.cpp
164\skip class tcp_server
165\until public:
166
167The constructor initialises an acceptor to listen on TCP port 13.
168
169\until private:
170
171The function <tt>start_accept()</tt> creates a socket and initiates an
172asynchronous accept operation to wait for a new connection.
173
174\until }
175
176The function <tt>handle_accept()</tt> is called when the asynchronous accept
177operation initiated by <tt>start_accept()</tt> finishes. It services the client
178request, and then calls <tt>start_accept()</tt> to initiate the next accept
179operation.
180
181\until }
182\until }
183
184\section tutdaytime3classtcp_connection The tcp_connection class
185
186We will use <tt>shared_ptr</tt> and <tt>enable_shared_from_this</tt> because we
187want to keep the <tt>tcp_connection</tt> object alive as long as there is an
188operation that refers to it.
189
190\dontinclude daytime3/server.cpp
191\skip class tcp_connection
192\until shared_ptr
193\until }
194\until }
195
196In the function <tt>start()</tt>, we call boost::asio::async_write() to serve the data
197to the client. Note that we are using boost::asio::async_write(), rather than
198boost::asio::ip::tcp::socket::async_write_some(), to ensure that the entire block of
199data is sent.
200
201\until {
202
203The data to be sent is stored in the class member <tt>message_</tt> as we need
204to keep the data valid until the asynchronous operation is complete.
205
206\until message_
207
208When initiating the asynchronous operation, and if using boost::bind(), you
209must specify only the arguments that match the handler's parameter list. In
210this program, both of the argument placeholders (boost::asio::placeholders::error and
211boost::asio::placeholders::bytes_transferred) could potentially have been removed,
212since they are not being used in <tt>handle_write()</tt>.
213
214\until placeholders::bytes_transferred
215
216Any further actions for this client connection are now the responsibility of
217<tt>handle_write()</tt>.
218
219\until };
220
221\section tutdaytime3remunused Removing unused handler parameters
222
223You may have noticed that the <tt>error</tt>, and <tt>bytes_transferred</tt>
224parameters are not used in the body of the <tt>handle_write()</tt> function. If
225parameters are not needed, it is possible to remove them from the function so
226that it looks like:
227
228\code
229  void handle_write()
230  {
231  }
232\endcode
233
234The boost::asio::async_write() call used to initiate the call can then be changed to
235just:
236
237\code
238  boost::asio::async_write(socket_, boost::asio::buffer(message_),
239      boost::bind(&tcp_connection::handle_write, shared_from_this()));
240\endcode
241
242See the \ref tutdaytime3src "full source listing" \n
243Return to the \ref index "tutorial index" \n
244Previous: \ref tutdaytime2 \n
245Next: \ref tutdaytime4
246
247*/
248
249/**
250\page tutdaytime3src Source listing for Daytime.3
251\include daytime3/server.cpp
252Return to \ref tutdaytime3
253*/
254
255/**
256\page tutdaytime4 Daytime.4 - A synchronous UDP daytime client
257
258This tutorial program shows how to use asio to implement a client application
259with UDP.
260
261\dontinclude daytime4/client.cpp
262\skip #include
263\until using boost::asio::ip::udp;
264
265The start of the application is essentially the same as for the TCP daytime
266client.
267
268\until boost::asio::io_context
269
270We use an boost::asio::ip::udp::resolver object to find the correct remote endpoint to
271use based on the host and service names. The query is restricted to return only
272IPv4 endpoints by the boost::asio::ip::udp::v4() argument.
273
274\until udp::v4
275
276The boost::asio::ip::udp::resolver::resolve() function is guaranteed to return at
277least one endpoint in the list if it does not fail. This means it is safe to
278dereference the return value directly.
279
280Since UDP is datagram-oriented, we will not be using a stream socket. Create an
281boost::asio::ip::udp::socket and initiate contact with the remote endpoint.
282
283\until receiver_endpoint
284
285Now we need to be ready to accept whatever the server sends back to us. The
286endpoint on our side that receives the server's response will be initialised by
287boost::asio::ip::udp::socket::receive_from().
288
289\until }
290
291Finally, handle any exceptions that may have been thrown.
292
293\until }
294\until }
295See the \ref tutdaytime4src "full source listing" \n
296Return to the \ref index "tutorial index" \n
297Previous: \ref tutdaytime3 \n
298Next: \ref tutdaytime5
299
300*/
301
302/**
303\page tutdaytime4src Source listing for Daytime.4
304\include daytime4/client.cpp
305Return to \ref tutdaytime4
306*/
307
308/**
309\page tutdaytime5 Daytime.5 - A synchronous UDP daytime server
310
311This tutorial program shows how to use asio to implement a server application
312with UDP.
313
314\dontinclude daytime5/server.cpp
315\skip int main()
316\until boost::asio::io_context
317
318Create an boost::asio::ip::udp::socket object to receive requests on UDP port 13.
319
320\until udp::socket
321
322Wait for a client to initiate contact with us. The remote_endpoint object will
323be populated by boost::asio::ip::udp::socket::receive_from().
324
325\until receive_from
326
327Determine what we are going to send back to the client.
328
329\until std::string message
330
331Send the response to the remote_endpoint.
332
333\until }
334\until }
335
336Finally, handle any exceptions.
337
338\until }
339\until }
340
341See the \ref tutdaytime5src "full source listing" \n
342Return to the \ref index "tutorial index" \n
343Previous: \ref tutdaytime4 \n
344Next: \ref tutdaytime6
345
346*/
347
348/**
349\page tutdaytime5src Source listing for Daytime.5
350\include daytime5/server.cpp
351Return to \ref tutdaytime5
352*/
353
354/**
355\page tutdaytime6 Daytime.6 - An asynchronous UDP daytime server
356
357\section tutdaytime6funcmain The main() function
358
359\dontinclude daytime6/server.cpp
360\skip int main()
361\until try
362\until {
363
364Create a server object to accept incoming client requests, and run
365the boost::asio::io_context object.
366
367\until return 0;
368\until }
369
370\section tutdaytime6classudp_server The udp_server class
371
372\dontinclude daytime6/server.cpp
373\skip class udp_server
374\until public:
375
376The constructor initialises a socket to listen on UDP port 13.
377
378\until private:
379\until {
380
381The function boost::asio::ip::udp::socket::async_receive_from() will cause the
382application to listen in the background for a new request. When such a request
383is received, the boost::asio::io_context object will invoke the
384<tt>handle_receive()</tt> function with two arguments: a value of type
385boost::system::error_code indicating whether the operation succeeded or failed, and a
386<tt>size_t</tt> value <tt>bytes_transferred</tt> specifying the number of bytes
387received.
388
389\until }
390
391The function <tt>handle_receive()</tt> will service the client request.
392
393\until {
394
395The <tt>error</tt> parameter contains the result of the asynchronous operation.
396Since we only provide the 1-byte <tt>recv_buffer_</tt> to contain the client's
397request, the boost::asio::io_context object would return an error if the client sent
398anything larger. We can ignore such an error if it comes up.
399
400\until {
401
402Determine what we are going to send.
403
404\until make_daytime_string()
405
406We now call boost::asio::ip::udp::socket::async_send_to() to serve the data to the
407client.
408
409\until boost::asio::placeholders::bytes_transferred
410
411When initiating the asynchronous operation, and if using boost::bind(), you
412must specify only the arguments that match the handler's parameter list. In
413this program, both of the argument placeholders (boost::asio::placeholders::error and
414boost::asio::placeholders::bytes_transferred) could potentially have been removed.
415
416Start listening for the next client request.
417
418\until start_receive
419
420Any further actions for this client request are now the responsibility of
421<tt>handle_send()</tt>.
422
423\until }
424\until }
425
426The function <tt>handle_send()</tt> is invoked after the service request has
427been completed.
428
429\until }
430\until }
431
432See the \ref tutdaytime6src "full source listing" \n
433Return to the \ref index "tutorial index" \n
434Previous: \ref tutdaytime5 \n
435Next: \ref tutdaytime7
436
437*/
438
439/**
440\page tutdaytime6src Source listing for Daytime.6
441\include daytime6/server.cpp
442Return to \ref tutdaytime6
443*/
444
445/**
446\page tutdaytime7 Daytime.7 - A combined TCP/UDP asynchronous server
447
448This tutorial program shows how to combine the two asynchronous servers that we
449have just written, into a single server application.
450
451\section tutdaytime7funcmain The main() function
452
453\dontinclude daytime7/server.cpp
454\skip int main()
455\until boost::asio::io_context
456
457We will begin by creating a server object to accept a TCP client connection.
458
459\until tcp_server
460
461We also need a server object to accept a UDP client request.
462
463\until udp_server
464
465We have created two lots of work for the boost::asio::io_context object to do.
466
467\until return 0;
468\until }
469
470\section tutdaytime7classtcp The tcp_connection and tcp_server classes
471
472The following two classes are taken from \ref tutdaytime3 "Daytime.3".
473
474\dontinclude daytime7/server.cpp
475\skip class tcp_connection
476\until };
477\until };
478
479\section tutdaytime7classudp The udp_server class
480
481Similarly, this next class is taken from the
482\ref tutdaytime6 "previous tutorial step".
483
484\dontinclude daytime7/server.cpp
485\skip class udp_server
486\until };
487
488See the \ref tutdaytime7src "full source listing" \n
489Return to the \ref index "tutorial index" \n
490Previous: \ref tutdaytime6
491
492*/
493
494/**
495\page tutdaytime7src Source listing for Daytime.7
496\include daytime7/server.cpp
497Return to \ref tutdaytime7
498*/
499