mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Squashed 'OpenVPN Adapter/Vendors/asio/' content from commit 524288c
git-subtree-dir: OpenVPN Adapter/Vendors/asio git-subtree-split: 524288cb4fcf84664b3dc39cb4424c7509969b92
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
[/
|
||||
/ Copyright (c) 2003-2016 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 Asio Anatomy]
|
||||
|
||||
Asio may be used to perform both synchronous and asynchronous operations on I/O
|
||||
objects such as sockets. Before using Asio it may be useful to get a conceptual
|
||||
picture of the various parts of 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.
|
||||
|
||||
[$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.
|
||||
|
||||
asio::io_context io_context;
|
||||
|
||||
To perform I/O operations [*your program] will need an [*I/O object] such as a
|
||||
TCP socket:
|
||||
|
||||
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 `asio::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 `asio::system_error` if the
|
||||
operation failed. If the code to initiate the operation had instead been
|
||||
written as:
|
||||
|
||||
asio::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.
|
||||
|
||||
[$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 asio::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.)
|
||||
|
||||
[$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 Asio operates. You will want to delve
|
||||
further into the documentation if your needs are more advanced, such as
|
||||
extending Asio to perform other types of asynchronous operations.
|
||||
|
||||
[endsect]
|
||||
Reference in New Issue
Block a user