168 lines
11 KiB
HTML
168 lines
11 KiB
HTML
|
<html>
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
<title>Basic Asio Anatomy</title>
|
||
|
<link rel="stylesheet" href="../../boostbook.css" type="text/css">
|
||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||
|
<link rel="home" href="../../index.html" title="Asio">
|
||
|
<link rel="up" href="../overview.html" title="Overview">
|
||
|
<link rel="prev" href="rationale.html" title="Rationale">
|
||
|
<link rel="next" href="model.html" title="Asynchronous Model">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
</head>
|
||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||
|
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../asio.png"></td></tr></table>
|
||
|
<hr>
|
||
|
<div class="spirit-nav">
|
||
|
<a accesskey="p" href="rationale.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../overview.html"><img src="../../up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../home.png" alt="Home"></a><a accesskey="n" href="model.html"><img src="../../next.png" alt="Next"></a>
|
||
|
</div>
|
||
|
<div class="section">
|
||
|
<div class="titlepage"><div><div><h3 class="title">
|
||
|
<a name="asio.overview.basics"></a><a class="link" href="basics.html" title="Basic Asio Anatomy">Basic Asio Anatomy</a>
|
||
|
</h3></div></div></div>
|
||
|
<p>
|
||
|
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.
|
||
|
</p>
|
||
|
<p>
|
||
|
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.
|
||
|
</p>
|
||
|
<p>
|
||
|
<span class="inlinemediaobject"><img src="../../sync_op.png"></span>
|
||
|
</p>
|
||
|
<p>
|
||
|
<span class="bold"><strong>Your program</strong></span> will have at least one <span class="bold"><strong>I/O execution context</strong></span>, such as an <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span></code>
|
||
|
object, <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">thread_pool</span></code> object, or <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">system_context</span></code>.
|
||
|
This <span class="bold"><strong>I/O execution context</strong></span> represents <span class="bold"><strong>your program</strong></span>'s link to the <span class="bold"><strong>operating
|
||
|
system</strong></span>'s I/O services.
|
||
|
</p>
|
||
|
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span> <span class="identifier">io_context</span><span class="special">;</span>
|
||
|
</pre>
|
||
|
<p>
|
||
|
To perform I/O operations <span class="bold"><strong>your program</strong></span> will
|
||
|
need an <span class="bold"><strong>I/O object</strong></span> such as a TCP socket:
|
||
|
</p>
|
||
|
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span> <span class="identifier">socket</span><span class="special">(</span><span class="identifier">io_context</span><span class="special">);</span>
|
||
|
</pre>
|
||
|
<p>
|
||
|
When a synchronous connect operation is performed, the following sequence
|
||
|
of events occurs:
|
||
|
</p>
|
||
|
<p>
|
||
|
1. <span class="bold"><strong>Your program</strong></span> initiates the connect operation
|
||
|
by calling the <span class="bold"><strong>I/O object</strong></span>:
|
||
|
</p>
|
||
|
<pre class="programlisting"><span class="identifier">socket</span><span class="special">.</span><span class="identifier">connect</span><span class="special">(</span><span class="identifier">server_endpoint</span><span class="special">);</span>
|
||
|
</pre>
|
||
|
<p>
|
||
|
2. The <span class="bold"><strong>I/O object</strong></span> forwards the request to
|
||
|
the <span class="bold"><strong>I/O execution context</strong></span>.
|
||
|
</p>
|
||
|
<p>
|
||
|
3. The <span class="bold"><strong>I/O execution context</strong></span> calls on the
|
||
|
<span class="bold"><strong>operating system</strong></span> to perform the connect
|
||
|
operation.
|
||
|
</p>
|
||
|
<p>
|
||
|
4. The <span class="bold"><strong>operating system</strong></span> returns the result
|
||
|
of the operation to the <span class="bold"><strong>I/O execution context</strong></span>.
|
||
|
</p>
|
||
|
<p>
|
||
|
5. The <span class="bold"><strong>I/O execution context</strong></span> translates
|
||
|
any error resulting from the operation into an object of type <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span></code>. An <code class="computeroutput"><span class="identifier">error_code</span></code>
|
||
|
may be compared with specific values, or tested as a boolean (where a <code class="computeroutput"><span class="keyword">false</span></code> result means that no error occurred).
|
||
|
The result is then forwarded back up to the <span class="bold"><strong>I/O object</strong></span>.
|
||
|
</p>
|
||
|
<p>
|
||
|
6. The <span class="bold"><strong>I/O object</strong></span> throws an exception of
|
||
|
type <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">system_error</span></code> if the operation failed. If
|
||
|
the code to initiate the operation had instead been written as:
|
||
|
</p>
|
||
|
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">;</span>
|
||
|
<span class="identifier">socket</span><span class="special">.</span><span class="identifier">connect</span><span class="special">(</span><span class="identifier">server_endpoint</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
|
||
|
</pre>
|
||
|
<p>
|
||
|
then the <code class="computeroutput"><span class="identifier">error_code</span></code> variable
|
||
|
<code class="computeroutput"><span class="identifier">ec</span></code> would be set to the result
|
||
|
of the operation, and no exception would be thrown.
|
||
|
</p>
|
||
|
<p>
|
||
|
When an asynchronous operation is used, a different sequence of events occurs.
|
||
|
</p>
|
||
|
<p>
|
||
|
<span class="inlinemediaobject"><img src="../../async_op1.png"></span>
|
||
|
</p>
|
||
|
<p>
|
||
|
1. <span class="bold"><strong>Your program</strong></span> initiates the connect operation
|
||
|
by calling the <span class="bold"><strong>I/O object</strong></span>:
|
||
|
</p>
|
||
|
<pre class="programlisting"><span class="identifier">socket</span><span class="special">.</span><span class="identifier">async_connect</span><span class="special">(</span><span class="identifier">server_endpoint</span><span class="special">,</span> <span class="identifier">your_completion_handler</span><span class="special">);</span>
|
||
|
</pre>
|
||
|
<p>
|
||
|
where <code class="computeroutput"><span class="identifier">your_completion_handler</span></code>
|
||
|
is a function or function object with the signature:
|
||
|
</p>
|
||
|
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">your_completion_handler</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">&</span> <span class="identifier">ec</span><span class="special">);</span>
|
||
|
</pre>
|
||
|
<p>
|
||
|
The exact signature required depends on the asynchronous operation being
|
||
|
performed. The reference documentation indicates the appropriate form for
|
||
|
each operation.
|
||
|
</p>
|
||
|
<p>
|
||
|
2. The <span class="bold"><strong>I/O object</strong></span> forwards the request to
|
||
|
the <span class="bold"><strong>I/O execution context</strong></span>.
|
||
|
</p>
|
||
|
<p>
|
||
|
3. The <span class="bold"><strong>I/O execution context</strong></span> signals to
|
||
|
the <span class="bold"><strong>operating system</strong></span> that it should start
|
||
|
an asynchronous connect.
|
||
|
</p>
|
||
|
<p>
|
||
|
Time passes. (In the synchronous case this wait would have been contained
|
||
|
entirely within the duration of the connect operation.)
|
||
|
</p>
|
||
|
<p>
|
||
|
<span class="inlinemediaobject"><img src="../../async_op2.png"></span>
|
||
|
</p>
|
||
|
<p>
|
||
|
4. The <span class="bold"><strong>operating system</strong></span> indicates that the
|
||
|
connect operation has completed by placing the result on a queue, ready to
|
||
|
be picked up by the <span class="bold"><strong>I/O execution context</strong></span>.
|
||
|
</p>
|
||
|
<p>
|
||
|
5. When using an <code class="computeroutput"><span class="identifier">io_context</span></code>
|
||
|
as the <span class="bold"><strong>I/O execution context</strong></span>, <span class="bold"><strong>your program</strong></span> must make a call to <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code>
|
||
|
(or to one of the similar <code class="computeroutput"><span class="identifier">io_context</span></code>
|
||
|
member functions) in order for the result to be retrieved. A call to <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code> blocks
|
||
|
while there are unfinished asynchronous operations, so you would typically
|
||
|
call it as soon as you have started your first asynchronous operation.
|
||
|
</p>
|
||
|
<p>
|
||
|
6. While inside the call to <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code>,
|
||
|
the <span class="bold"><strong>I/O execution context</strong></span> dequeues the result
|
||
|
of the operation, translates it into an <code class="computeroutput"><span class="identifier">error_code</span></code>,
|
||
|
and then passes it to <span class="bold"><strong>your completion handler</strong></span>.
|
||
|
</p>
|
||
|
<p>
|
||
|
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.
|
||
|
</p>
|
||
|
</div>
|
||
|
<div class="copyright-footer">Copyright © 2003-2023 Christopher M. Kohlhoff<p>
|
||
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||
|
</p>
|
||
|
</div>
|
||
|
<hr>
|
||
|
<div class="spirit-nav">
|
||
|
<a accesskey="p" href="rationale.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../overview.html"><img src="../../up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../home.png" alt="Home"></a><a accesskey="n" href="model.html"><img src="../../next.png" alt="Next"></a>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|