107 lines
3.9 KiB
Plaintext
107 lines
3.9 KiB
Plaintext
[/
|
|
/ Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
|
/
|
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
/]
|
|
|
|
[section:basics Basic Boost.Asio Anatomy]
|
|
|
|
Boost.Asio may be used to perform both synchronous and asynchronous operations on I/O
|
|
objects such as sockets. Before using Boost.Asio it may be useful to get a conceptual
|
|
picture of the various parts of Boost.Asio, your program, and how they work together.
|
|
|
|
As an introductory example, let's consider what happens when you perform a
|
|
connect operation on a socket. We shall start by examining synchronous
|
|
operations.
|
|
|
|
[$boost_asio/sync_op.png]
|
|
|
|
[*Your program] will have at least one [*io_context] object. The [*io_context]
|
|
represents [*your program]'s link to the [*operating system]'s I/O services.
|
|
|
|
boost::asio::io_context io_context;
|
|
|
|
To perform I/O operations [*your program] will need an [*I/O object] such as a
|
|
TCP socket:
|
|
|
|
boost::asio::ip::tcp::socket socket(io_context);
|
|
|
|
When a synchronous connect operation is performed, the following sequence of
|
|
events occurs:
|
|
|
|
1. [*Your program] initiates the connect operation by calling the [*I/O
|
|
object]:
|
|
|
|
socket.connect(server_endpoint);
|
|
|
|
2. The [*I/O object] forwards the request to the [*io_context].
|
|
|
|
3. The [*io_context] calls on the [*operating system] to perform the connect
|
|
operation.
|
|
|
|
4. The [*operating system] returns the result of the operation to the
|
|
[*io_context].
|
|
|
|
5. The [*io_context] translates any error resulting from the operation into an
|
|
object of type `boost::system::error_code`. An `error_code` may be compared with
|
|
specific values, or tested as a boolean (where a `false` result means that no
|
|
error occurred). The result is then forwarded back up to the [*I/O object].
|
|
|
|
6. The [*I/O object] throws an exception of type `boost::system::system_error` if the
|
|
operation failed. If the code to initiate the operation had instead been
|
|
written as:
|
|
|
|
boost::system::error_code ec;
|
|
socket.connect(server_endpoint, ec);
|
|
|
|
then the `error_code` variable `ec` would be set to the result of the
|
|
operation, and no exception would be thrown.
|
|
|
|
When an asynchronous operation is used, a different sequence of events occurs.
|
|
|
|
[$boost_asio/async_op1.png]
|
|
|
|
1. [*Your program] initiates the connect operation by calling the [*I/O
|
|
object]:
|
|
|
|
socket.async_connect(server_endpoint, your_completion_handler);
|
|
|
|
where `your_completion_handler` is a function or function object with the
|
|
signature:
|
|
|
|
void your_completion_handler(const boost::system::error_code& ec);
|
|
|
|
The exact signature required depends on the asynchronous operation being
|
|
performed. The reference documentation indicates the appropriate form for each
|
|
operation.
|
|
|
|
2. The [*I/O object] forwards the request to the [*io_context].
|
|
|
|
3. The [*io_context] signals to the [*operating system] that it should start an
|
|
asynchronous connect.
|
|
|
|
Time passes. (In the synchronous case this wait would have been contained
|
|
entirely within the duration of the connect operation.)
|
|
|
|
[$boost_asio/async_op2.png]
|
|
|
|
4. The [*operating system] indicates that the connect operation has completed
|
|
by placing the result on a queue, ready to be picked up by the [*io_context].
|
|
|
|
5. [*Your program] must make a call to `io_context::run()` (or to one of the
|
|
similar [*io_context] member functions) in order for the result to be
|
|
retrieved. A call to `io_context::run()` blocks while there are unfinished
|
|
asynchronous operations, so you would typically call it as soon as you have
|
|
started your first asynchronous operation.
|
|
|
|
6. While inside the call to `io_context::run()`, the [*io_context] dequeues the
|
|
result of the operation, translates it into an `error_code`, and then passes it
|
|
to [*your completion handler].
|
|
|
|
This is a simplified picture of how Boost.Asio operates. You will want to delve
|
|
further into the documentation if your needs are more advanced, such as
|
|
extending Boost.Asio to perform other types of asynchronous operations.
|
|
|
|
[endsect]
|