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