Adds asio library and Storage Module
This commit is contained in:
1 parent
79a6ee5779
commit
30439acd43
4869 files changed
+618801
-903
No files matched your search
@@ -0,0 +1,41 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>boost::bind</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime7/src.html" title="Source listing for Daytime.7">
|
||||
<link rel="next" href="../examples.html" title="Examples">
|
||||
</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="tutdaytime7/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="../examples.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.boost_bind"></a><a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
See the <a href="http://www.boost.org/libs/bind/bind.html" target="_top">Boost: bind.hpp
|
||||
documentation</a> for more information on how to use <code class="computeroutput">boost::bind</code>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime7/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="../examples.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,149 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.1 - A synchronous TCP daytime client</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tuttimer5/src.html" title="Source listing for Timer.5">
|
||||
<link rel="next" href="tutdaytime1/src.html" title="Source listing for Daytime.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="tuttimer5/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime1/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime1"></a><a class="link" href="tutdaytime1.html" title="Daytime.1 - A synchronous TCP daytime client">Daytime.1 - A synchronous
|
||||
TCP daytime client</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program shows how to use asio to implement a client application
|
||||
with TCP.
|
||||
</p>
|
||||
<p>
|
||||
We start by including the necessary header files.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <boost/array.hpp>
|
||||
#include <asio.hpp>
|
||||
</pre>
|
||||
<p>
|
||||
The purpose of this application is to access a daytime service, so we need
|
||||
the user to specify the server.
|
||||
</p>
|
||||
<pre class="programlisting">using asio::ip::tcp;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage: client <host>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
All programs that use asio need to have at least one I/O execution context,
|
||||
such as an <a class="link" href="../reference/io_context.html" title="io_context">io_context</a> object.
|
||||
</p>
|
||||
<pre class="programlisting"> asio::io_context io_context;
|
||||
</pre>
|
||||
<p>
|
||||
We need to turn the server name that was specified as a parameter to the
|
||||
application, into a TCP endpoint. To do this we use an <a class="link" href="../reference/ip__tcp/resolver.html" title="ip::tcp::resolver">ip::tcp::resolver</a>
|
||||
object.
|
||||
</p>
|
||||
<pre class="programlisting"> tcp::resolver resolver(io_context);
|
||||
</pre>
|
||||
<p>
|
||||
A resolver takes a host name and service name and turns them into a list
|
||||
of endpoints. We perform a resolve call using the name of the server, specified
|
||||
in <code class="computeroutput">argv[1]</code>, and the name of the service, in this case <code class="computeroutput">"daytime"</code>.
|
||||
</p>
|
||||
<p>
|
||||
The list of endpoints is returned using an object of type <a class="link" href="../reference/ip__basic_resolver/results_type.html" title="ip::basic_resolver::results_type">ip::tcp::resolver::results_type</a>.
|
||||
This object is a range, with begin() and end() member functions that may
|
||||
be used for iterating over the results.
|
||||
</p>
|
||||
<pre class="programlisting"> tcp::resolver::results_type endpoints =
|
||||
resolver.resolve(argv[1], "daytime");
|
||||
</pre>
|
||||
<p>
|
||||
Now we create and connect the socket. The list of endpoints obtained above
|
||||
may contain both IPv4 and IPv6 endpoints, so we need to try each of them
|
||||
until we find one that works. This keeps the client program independent of
|
||||
a specific IP version. The asio::connect() function does this for us automatically.
|
||||
</p>
|
||||
<pre class="programlisting"> tcp::socket socket(io_context);
|
||||
asio::connect(socket, endpoints);
|
||||
</pre>
|
||||
<p>
|
||||
The connection is open. All we need to do now is read the response from the
|
||||
daytime service.
|
||||
</p>
|
||||
<p>
|
||||
We use a <code class="computeroutput">boost::array</code> to hold the received data. The asio::buffer()
|
||||
function automatically determines the size of the array to help prevent buffer
|
||||
overruns. Instead of a <code class="computeroutput">boost::array</code>, we could have used a <code class="computeroutput">char
|
||||
[]</code> or <code class="computeroutput">std::vector</code>.
|
||||
</p>
|
||||
<pre class="programlisting"> for (;;)
|
||||
{
|
||||
boost::array<char, 128> buf;
|
||||
asio::error_code error;
|
||||
|
||||
size_t len = socket.read_some(asio::buffer(buf), error);
|
||||
</pre>
|
||||
<p>
|
||||
When the server closes the connection, the <a class="link" href="../reference/basic_stream_socket/read_some.html" title="basic_stream_socket::read_some">ip::tcp::socket::read_some()</a>
|
||||
function will exit with the asio::error::eof error, which is how we know
|
||||
to exit the loop.
|
||||
</p>
|
||||
<pre class="programlisting"> if (error == asio::error::eof)
|
||||
break; // Connection closed cleanly by peer.
|
||||
else if (error)
|
||||
throw asio::system_error(error); // Some other error.
|
||||
|
||||
std::cout.write(buf.data(), len);
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Finally, handle any exceptions that may have been thrown.
|
||||
</p>
|
||||
<pre class="programlisting"> }
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime1/src.html" title="Source listing for Daytime.1">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">Daytime.2 - A synchronous
|
||||
TCP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tuttimer5/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime1/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,99 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.1</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="../tutdaytime1.html" title="Daytime.1 - A synchronous TCP daytime client">
|
||||
<link rel="prev" href="../tutdaytime1.html" title="Daytime.1 - A synchronous TCP daytime client">
|
||||
<link rel="next" href="../tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">
|
||||
</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="../tutdaytime1.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime1.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="../tutdaytime2.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime1.src"></a><a class="link" href="src.html" title="Source listing for Daytime.1">Source listing for Daytime.1</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// client.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/array.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage: client <host>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
asio::io_context io_context;
|
||||
|
||||
tcp::resolver resolver(io_context);
|
||||
tcp::resolver::results_type endpoints =
|
||||
resolver.resolve(argv[1], "daytime");
|
||||
|
||||
tcp::socket socket(io_context);
|
||||
asio::connect(socket, endpoints);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
boost::array<char, 128> buf;
|
||||
asio::error_code error;
|
||||
|
||||
size_t len = socket.read_some(asio::buffer(buf), error);
|
||||
|
||||
if (error == asio::error::eof)
|
||||
break; // Connection closed cleanly by peer.
|
||||
else if (error)
|
||||
throw asio::system_error(error); // Some other error.
|
||||
|
||||
std::cout.write(buf.data(), len);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime1.html" title="Daytime.1 - A synchronous TCP daytime client">Daytime.1 - A synchronous
|
||||
TCP daytime client</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime1.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime1.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="../tutdaytime2.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,120 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.2 - A synchronous TCP daytime server</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime1/src.html" title="Source listing for Daytime.1">
|
||||
<link rel="next" href="tutdaytime2/src.html" title="Source listing for Daytime.2">
|
||||
</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="tutdaytime1/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime2/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime2"></a><a class="link" href="tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">Daytime.2 - A synchronous
|
||||
TCP daytime server</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program shows how to use asio to implement a server application
|
||||
with TCP.
|
||||
</p>
|
||||
<pre class="programlisting">#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::tcp;
|
||||
</pre>
|
||||
<p>
|
||||
We define the function <code class="computeroutput">make_daytime_string()</code> to create the string
|
||||
to be sent back to the client. This function will be reused in all of our
|
||||
daytime server applications.
|
||||
</p>
|
||||
<pre class="programlisting">std::string make_daytime_string()
|
||||
{
|
||||
using namespace std; // For time_t, time and ctime;
|
||||
time_t now = time(0);
|
||||
return ctime(&now);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
</pre>
|
||||
<p>
|
||||
A <a class="link" href="../reference/ip__tcp/acceptor.html" title="ip::tcp::acceptor">ip::tcp::acceptor</a>
|
||||
object needs to be created to listen for new connections. It is initialised
|
||||
to listen on TCP port 13, for IP version 4.
|
||||
</p>
|
||||
<pre class="programlisting"> tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 13));
|
||||
</pre>
|
||||
<p>
|
||||
This is an iterative server, which means that it will handle one connection
|
||||
at a time. Create a socket that will represent the connection to the client,
|
||||
and then wait for a connection.
|
||||
</p>
|
||||
<pre class="programlisting"> for (;;)
|
||||
{
|
||||
tcp::socket socket(io_context);
|
||||
acceptor.accept(socket);
|
||||
</pre>
|
||||
<p>
|
||||
A client is accessing our service. Determine the current time and transfer
|
||||
this information to the client.
|
||||
</p>
|
||||
<pre class="programlisting"> std::string message = make_daytime_string();
|
||||
|
||||
asio::error_code ignored_error;
|
||||
asio::write(socket, asio::buffer(message), ignored_error);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Finally, handle any exceptions.
|
||||
</p>
|
||||
<pre class="programlisting"> catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime2/src.html" title="Source listing for Daytime.2">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tutdaytime1.html" title="Daytime.1 - A synchronous TCP daytime client">Daytime.1 - A synchronous
|
||||
TCP daytime client</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">Daytime.3 - An asynchronous
|
||||
TCP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime1/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime2/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,92 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.2</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="../tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">
|
||||
<link rel="prev" href="../tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">
|
||||
<link rel="next" href="../tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">
|
||||
</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="../tutdaytime2.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime2.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="../tutdaytime3.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime2.src"></a><a class="link" href="src.html" title="Source listing for Daytime.2">Source listing for Daytime.2</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// server.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
std::string make_daytime_string()
|
||||
{
|
||||
using namespace std; // For time_t, time and ctime;
|
||||
time_t now = time(0);
|
||||
return ctime(&now);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
|
||||
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 13));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
tcp::socket socket(io_context);
|
||||
acceptor.accept(socket);
|
||||
|
||||
std::string message = make_daytime_string();
|
||||
|
||||
asio::error_code ignored_error;
|
||||
asio::write(socket, asio::buffer(message), ignored_error);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">Daytime.2 - A synchronous
|
||||
TCP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime2.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime2.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="../tutdaytime3.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,232 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.3 - An asynchronous TCP daytime server</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime2/src.html" title="Source listing for Daytime.2">
|
||||
<link rel="next" href="tutdaytime3/src.html" title="Source listing for Daytime.3">
|
||||
</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="tutdaytime2/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime3/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime3"></a><a class="link" href="tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">Daytime.3 - An asynchronous
|
||||
TCP daytime server</a>
|
||||
</h3></div></div></div>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime3.h0"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime3.the_main___function"></a></span><a class="link" href="tutdaytime3.html#asio.tutorial.tutdaytime3.the_main___function">The
|
||||
main() function</a>
|
||||
</h5>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
We need to create a server object to accept incoming client connections.
|
||||
The <a class="link" href="../reference/io_context.html" title="io_context">io_context</a> object provides
|
||||
I/O services, such as sockets, that the server object will use.
|
||||
</p>
|
||||
<pre class="programlisting"> asio::io_context io_context;
|
||||
tcp_server server(io_context);
|
||||
</pre>
|
||||
<p>
|
||||
Run the <a class="link" href="../reference/io_context.html" title="io_context">io_context</a> object
|
||||
so that it will perform asynchronous operations on your behalf.
|
||||
</p>
|
||||
<pre class="programlisting"> io_context.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime3.h1"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime3.the_tcp_server_class"></a></span><a class="link" href="tutdaytime3.html#asio.tutorial.tutdaytime3.the_tcp_server_class">The
|
||||
tcp_server class</a>
|
||||
</h5>
|
||||
<pre class="programlisting">class tcp_server
|
||||
{
|
||||
public:
|
||||
</pre>
|
||||
<p>
|
||||
The constructor initialises an acceptor to listen on TCP port 13.
|
||||
</p>
|
||||
<pre class="programlisting"> tcp_server(asio::io_context& io_context)
|
||||
: io_context_(io_context),
|
||||
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
|
||||
{
|
||||
start_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
</pre>
|
||||
<p>
|
||||
The function <code class="computeroutput">start_accept()</code> creates a socket and initiates an
|
||||
asynchronous accept operation to wait for a new connection.
|
||||
</p>
|
||||
<pre class="programlisting"> void start_accept()
|
||||
{
|
||||
tcp_connection::pointer new_connection =
|
||||
tcp_connection::create(io_context_);
|
||||
|
||||
acceptor_.async_accept(new_connection->socket(),
|
||||
boost::bind(&tcp_server::handle_accept, this, new_connection,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The function <code class="computeroutput">handle_accept()</code> is called when the asynchronous
|
||||
accept operation initiated by <code class="computeroutput">start_accept()</code> finishes. It services
|
||||
the client request, and then calls <code class="computeroutput">start_accept()</code> to initiate
|
||||
the next accept operation.
|
||||
</p>
|
||||
<pre class="programlisting"> void handle_accept(tcp_connection::pointer new_connection,
|
||||
const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
new_connection->start();
|
||||
}
|
||||
|
||||
start_accept();
|
||||
}
|
||||
</pre>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime3.h2"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime3.the_tcp_connection_class"></a></span><a class="link" href="tutdaytime3.html#asio.tutorial.tutdaytime3.the_tcp_connection_class">The
|
||||
tcp_connection class</a>
|
||||
</h5>
|
||||
<p>
|
||||
We will use <code class="computeroutput">shared_ptr</code> and <code class="computeroutput">enable_shared_from_this</code>
|
||||
because we want to keep the <code class="computeroutput">tcp_connection</code> object alive as long
|
||||
as there is an operation that refers to it.
|
||||
</p>
|
||||
<pre class="programlisting">class tcp_connection
|
||||
: public boost::enable_shared_from_this<tcp_connection>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<tcp_connection> pointer;
|
||||
|
||||
static pointer create(asio::io_context& io_context)
|
||||
{
|
||||
return pointer(new tcp_connection(io_context));
|
||||
}
|
||||
|
||||
tcp::socket& socket()
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
In the function <code class="computeroutput">start()</code>, we call asio::async_write() to serve
|
||||
the data to the client. Note that we are using asio::async_write(), rather
|
||||
than <a class="link" href="../reference/basic_stream_socket/async_write_some.html" title="basic_stream_socket::async_write_some">ip::tcp::socket::async_write_some()</a>,
|
||||
to ensure that the entire block of data is sent.
|
||||
</p>
|
||||
<pre class="programlisting"> void start()
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
The data to be sent is stored in the class member <code class="computeroutput">message_</code> as
|
||||
we need to keep the data valid until the asynchronous operation is complete.
|
||||
</p>
|
||||
<pre class="programlisting"> message_ = make_daytime_string();
|
||||
</pre>
|
||||
<p>
|
||||
When initiating the asynchronous operation, and if using <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a>
|
||||
, you must specify only the arguments that match the handler's parameter
|
||||
list. In this program, both of the argument placeholders (asio::placeholders::error
|
||||
and asio::placeholders::bytes_transferred) could potentially have been removed,
|
||||
since they are not being used in <code class="computeroutput">handle_write()</code>.
|
||||
</p>
|
||||
<pre class="programlisting"> asio::async_write(socket_, asio::buffer(message_),
|
||||
boost::bind(&tcp_connection::handle_write, shared_from_this(),
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
</pre>
|
||||
<p>
|
||||
Any further actions for this client connection are now the responsibility
|
||||
of <code class="computeroutput">handle_write()</code>.
|
||||
</p>
|
||||
<pre class="programlisting"> }
|
||||
|
||||
private:
|
||||
tcp_connection(asio::io_context& io_context)
|
||||
: socket_(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
void handle_write(const asio::error_code& /*error*/,
|
||||
size_t /*bytes_transferred*/)
|
||||
{
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
std::string message_;
|
||||
};
|
||||
</pre>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime3.h3"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime3.removing_unused_handler_parameters"></a></span><a class="link" href="tutdaytime3.html#asio.tutorial.tutdaytime3.removing_unused_handler_parameters">Removing
|
||||
unused handler parameters</a>
|
||||
</h5>
|
||||
<p>
|
||||
You may have noticed that the <code class="computeroutput">error</code>, and <code class="computeroutput">bytes_transferred</code>
|
||||
parameters are not used in the body of the <code class="computeroutput">handle_write()</code> function.
|
||||
If parameters are not needed, it is possible to remove them from the function
|
||||
so that it looks like:
|
||||
</p>
|
||||
<pre class="programlisting"> void handle_write()
|
||||
{
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The asio::async_write() call used to initiate the call can then be changed
|
||||
to just:
|
||||
</p>
|
||||
<pre class="programlisting"> asio::async_write(socket_, asio::buffer(message_),
|
||||
boost::bind(&tcp_connection::handle_write, shared_from_this()));
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime3/src.html" title="Source listing for Daytime.3">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tutdaytime2.html" title="Daytime.2 - A synchronous TCP daytime server">Daytime.2 - A synchronous
|
||||
TCP daytime server</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">Daytime.4 - A synchronous
|
||||
UDP daytime client</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime2/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime3/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,161 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.3</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="../tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">
|
||||
<link rel="prev" href="../tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">
|
||||
<link rel="next" href="../tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">
|
||||
</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="../tutdaytime3.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime3.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="../tutdaytime4.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime3.src"></a><a class="link" href="src.html" title="Source listing for Daytime.3">Source listing for Daytime.3</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// server.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
std::string make_daytime_string()
|
||||
{
|
||||
using namespace std; // For time_t, time and ctime;
|
||||
time_t now = time(0);
|
||||
return ctime(&now);
|
||||
}
|
||||
|
||||
class tcp_connection
|
||||
: public boost::enable_shared_from_this<tcp_connection>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<tcp_connection> pointer;
|
||||
|
||||
static pointer create(asio::io_context& io_context)
|
||||
{
|
||||
return pointer(new tcp_connection(io_context));
|
||||
}
|
||||
|
||||
tcp::socket& socket()
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
message_ = make_daytime_string();
|
||||
|
||||
asio::async_write(socket_, asio::buffer(message_),
|
||||
boost::bind(&tcp_connection::handle_write, shared_from_this(),
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
private:
|
||||
tcp_connection(asio::io_context& io_context)
|
||||
: socket_(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
void handle_write(const asio::error_code& /*error*/,
|
||||
size_t /*bytes_transferred*/)
|
||||
{
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
class tcp_server
|
||||
{
|
||||
public:
|
||||
tcp_server(asio::io_context& io_context)
|
||||
: io_context_(io_context),
|
||||
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
|
||||
{
|
||||
start_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_accept()
|
||||
{
|
||||
tcp_connection::pointer new_connection =
|
||||
tcp_connection::create(io_context_);
|
||||
|
||||
acceptor_.async_accept(new_connection->socket(),
|
||||
boost::bind(&tcp_server::handle_accept, this, new_connection,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_accept(tcp_connection::pointer new_connection,
|
||||
const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
new_connection->start();
|
||||
}
|
||||
|
||||
start_accept();
|
||||
}
|
||||
|
||||
asio::io_context& io_context_;
|
||||
tcp::acceptor acceptor_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
tcp_server server(io_context);
|
||||
io_context.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">Daytime.3 - An asynchronous
|
||||
TCP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime3.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime3.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="../tutdaytime4.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,127 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.4 - A synchronous UDP daytime client</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime3/src.html" title="Source listing for Daytime.3">
|
||||
<link rel="next" href="tutdaytime4/src.html" title="Source listing for Daytime.4">
|
||||
</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="tutdaytime3/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime4/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime4"></a><a class="link" href="tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">Daytime.4 - A synchronous
|
||||
UDP daytime client</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program shows how to use asio to implement a client application
|
||||
with UDP.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <boost/array.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::udp;
|
||||
</pre>
|
||||
<p>
|
||||
The start of the application is essentially the same as for the TCP daytime
|
||||
client.
|
||||
</p>
|
||||
<pre class="programlisting">int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage: client <host>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
asio::io_context io_context;
|
||||
</pre>
|
||||
<p>
|
||||
We use an <a class="link" href="../reference/ip__udp/resolver.html" title="ip::udp::resolver">ip::udp::resolver</a>
|
||||
object to find the correct remote endpoint to use based on the host and service
|
||||
names. The query is restricted to return only IPv4 endpoints by the <a class="link" href="../reference/ip__udp/v4.html" title="ip::udp::v4">ip::udp::v4()</a> argument.
|
||||
</p>
|
||||
<pre class="programlisting"> udp::resolver resolver(io_context);
|
||||
udp::endpoint receiver_endpoint =
|
||||
*resolver.resolve(udp::v4(), argv[1], "daytime").begin();
|
||||
</pre>
|
||||
<p>
|
||||
The <a class="link" href="../reference/ip__basic_resolver/resolve.html" title="ip::basic_resolver::resolve">ip::udp::resolver::resolve()</a>
|
||||
function is guaranteed to return at least one endpoint in the list if it
|
||||
does not fail. This means it is safe to dereference the return value directly.
|
||||
</p>
|
||||
<p>
|
||||
Since UDP is datagram-oriented, we will not be using a stream socket. Create
|
||||
an <a class="link" href="../reference/ip__udp/socket.html" title="ip::udp::socket">ip::udp::socket</a> and
|
||||
initiate contact with the remote endpoint.
|
||||
</p>
|
||||
<pre class="programlisting"> udp::socket socket(io_context);
|
||||
socket.open(udp::v4());
|
||||
|
||||
boost::array<char, 1> send_buf = {{ 0 }};
|
||||
socket.send_to(asio::buffer(send_buf), receiver_endpoint);
|
||||
</pre>
|
||||
<p>
|
||||
Now we need to be ready to accept whatever the server sends back to us. The
|
||||
endpoint on our side that receives the server's response will be initialised
|
||||
by <a class="link" href="../reference/basic_datagram_socket/receive_from.html" title="basic_datagram_socket::receive_from">ip::udp::socket::receive_from()</a>.
|
||||
</p>
|
||||
<pre class="programlisting"> boost::array<char, 128> recv_buf;
|
||||
udp::endpoint sender_endpoint;
|
||||
size_t len = socket.receive_from(
|
||||
asio::buffer(recv_buf), sender_endpoint);
|
||||
|
||||
std::cout.write(recv_buf.data(), len);
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Finally, handle any exceptions that may have been thrown.
|
||||
</p>
|
||||
<pre class="programlisting"> catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime4/src.html" title="Source listing for Daytime.4">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">Daytime.3 - An asynchronous
|
||||
TCP daytime server</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">Daytime.5 - A synchronous
|
||||
UDP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime3/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime4/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,94 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.4</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="../tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">
|
||||
<link rel="prev" href="../tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">
|
||||
<link rel="next" href="../tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">
|
||||
</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="../tutdaytime4.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime4.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="../tutdaytime5.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime4.src"></a><a class="link" href="src.html" title="Source listing for Daytime.4">Source listing for Daytime.4</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// client.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/array.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage: client <host>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
asio::io_context io_context;
|
||||
|
||||
udp::resolver resolver(io_context);
|
||||
udp::endpoint receiver_endpoint =
|
||||
*resolver.resolve(udp::v4(), argv[1], "daytime").begin();
|
||||
|
||||
udp::socket socket(io_context);
|
||||
socket.open(udp::v4());
|
||||
|
||||
boost::array<char, 1> send_buf = {{ 0 }};
|
||||
socket.send_to(asio::buffer(send_buf), receiver_endpoint);
|
||||
|
||||
boost::array<char, 128> recv_buf;
|
||||
udp::endpoint sender_endpoint;
|
||||
size_t len = socket.receive_from(
|
||||
asio::buffer(recv_buf), sender_endpoint);
|
||||
|
||||
std::cout.write(recv_buf.data(), len);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">Daytime.4 - A synchronous
|
||||
UDP daytime client</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime4.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime4.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="../tutdaytime5.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,103 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.5 - A synchronous UDP daytime server</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime4/src.html" title="Source listing for Daytime.4">
|
||||
<link rel="next" href="tutdaytime5/src.html" title="Source listing for Daytime.5">
|
||||
</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="tutdaytime4/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime5/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime5"></a><a class="link" href="tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">Daytime.5 - A synchronous
|
||||
UDP daytime server</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program shows how to use asio to implement a server application
|
||||
with UDP.
|
||||
</p>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
</pre>
|
||||
<p>
|
||||
Create an <a class="link" href="../reference/ip__udp/socket.html" title="ip::udp::socket">ip::udp::socket</a>
|
||||
object to receive requests on UDP port 13.
|
||||
</p>
|
||||
<pre class="programlisting"> udp::socket socket(io_context, udp::endpoint(udp::v4(), 13));
|
||||
</pre>
|
||||
<p>
|
||||
Wait for a client to initiate contact with us. The remote_endpoint object
|
||||
will be populated by <a class="link" href="../reference/basic_datagram_socket/receive_from.html" title="basic_datagram_socket::receive_from">ip::udp::socket::receive_from()</a>.
|
||||
</p>
|
||||
<pre class="programlisting"> for (;;)
|
||||
{
|
||||
boost::array<char, 1> recv_buf;
|
||||
udp::endpoint remote_endpoint;
|
||||
socket.receive_from(asio::buffer(recv_buf), remote_endpoint);
|
||||
</pre>
|
||||
<p>
|
||||
Determine what we are going to send back to the client.
|
||||
</p>
|
||||
<pre class="programlisting"> std::string message = make_daytime_string();
|
||||
</pre>
|
||||
<p>
|
||||
Send the response to the remote_endpoint.
|
||||
</p>
|
||||
<pre class="programlisting"> asio::error_code ignored_error;
|
||||
socket.send_to(asio::buffer(message),
|
||||
remote_endpoint, 0, ignored_error);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Finally, handle any exceptions.
|
||||
</p>
|
||||
<pre class="programlisting"> catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime5/src.html" title="Source listing for Daytime.5">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tutdaytime4.html" title="Daytime.4 - A synchronous UDP daytime client">Daytime.4 - A synchronous
|
||||
UDP daytime client</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">Daytime.6 - An asynchronous
|
||||
UDP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime4/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime5/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,95 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.5</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="../tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">
|
||||
<link rel="prev" href="../tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">
|
||||
<link rel="next" href="../tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">
|
||||
</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="../tutdaytime5.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime5.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="../tutdaytime6.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime5.src"></a><a class="link" href="src.html" title="Source listing for Daytime.5">Source listing for Daytime.5</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// server.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/array.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
std::string make_daytime_string()
|
||||
{
|
||||
using namespace std; // For time_t, time and ctime;
|
||||
time_t now = time(0);
|
||||
return ctime(&now);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
|
||||
udp::socket socket(io_context, udp::endpoint(udp::v4(), 13));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
boost::array<char, 1> recv_buf;
|
||||
udp::endpoint remote_endpoint;
|
||||
socket.receive_from(asio::buffer(recv_buf), remote_endpoint);
|
||||
|
||||
std::string message = make_daytime_string();
|
||||
|
||||
asio::error_code ignored_error;
|
||||
socket.send_to(asio::buffer(message),
|
||||
remote_endpoint, 0, ignored_error);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">Daytime.5 - A synchronous
|
||||
UDP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime5.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime5.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="../tutdaytime6.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,180 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.6 - An asynchronous UDP daytime server</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime5/src.html" title="Source listing for Daytime.5">
|
||||
<link rel="next" href="tutdaytime6/src.html" title="Source listing for Daytime.6">
|
||||
</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="tutdaytime5/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime6/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime6"></a><a class="link" href="tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">Daytime.6 - An asynchronous
|
||||
UDP daytime server</a>
|
||||
</h3></div></div></div>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime6.h0"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime6.the_main___function"></a></span><a class="link" href="tutdaytime6.html#asio.tutorial.tutdaytime6.the_main___function">The
|
||||
main() function</a>
|
||||
</h5>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
Create a server object to accept incoming client requests, and run the <a class="link" href="../reference/io_context.html" title="io_context">io_context</a> object.
|
||||
</p>
|
||||
<pre class="programlisting"> asio::io_context io_context;
|
||||
udp_server server(io_context);
|
||||
io_context.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime6.h1"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime6.the_udp_server_class"></a></span><a class="link" href="tutdaytime6.html#asio.tutorial.tutdaytime6.the_udp_server_class">The
|
||||
udp_server class</a>
|
||||
</h5>
|
||||
<pre class="programlisting">class udp_server
|
||||
{
|
||||
public:
|
||||
</pre>
|
||||
<p>
|
||||
The constructor initialises a socket to listen on UDP port 13.
|
||||
</p>
|
||||
<pre class="programlisting"> udp_server(asio::io_context& io_context)
|
||||
: socket_(io_context, udp::endpoint(udp::v4(), 13))
|
||||
{
|
||||
start_receive();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_receive()
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
The function <a class="link" href="../reference/basic_datagram_socket/async_receive_from.html" title="basic_datagram_socket::async_receive_from">ip::udp::socket::async_receive_from()</a>
|
||||
will cause the application to listen in the background for a new request.
|
||||
When such a request is received, the <a class="link" href="../reference/io_context.html" title="io_context">io_context</a>
|
||||
object will invoke the <code class="computeroutput">handle_receive()</code> function with two arguments:
|
||||
a value of type <a class="link" href="../reference/error_code.html" title="error_code">error_code</a>
|
||||
indicating whether the operation succeeded or failed, and a <code class="computeroutput">size_t</code>
|
||||
value <code class="computeroutput">bytes_transferred</code> specifying the number of bytes received.
|
||||
</p>
|
||||
<pre class="programlisting"> socket_.async_receive_from(
|
||||
asio::buffer(recv_buffer_), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_receive, this,
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The function <code class="computeroutput">handle_receive()</code> will service the client request.
|
||||
</p>
|
||||
<pre class="programlisting"> void handle_receive(const asio::error_code& error,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput">error</code> parameter contains the result of the asynchronous
|
||||
operation. Since we only provide the 1-byte <code class="computeroutput">recv_buffer_</code> to
|
||||
contain the client's request, the <a class="link" href="../reference/io_context.html" title="io_context">io_context</a>
|
||||
object would return an error if the client sent anything larger. We can ignore
|
||||
such an error if it comes up.
|
||||
</p>
|
||||
<pre class="programlisting"> if (!error)
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
Determine what we are going to send.
|
||||
</p>
|
||||
<pre class="programlisting"> boost::shared_ptr<std::string> message(
|
||||
new std::string(make_daytime_string()));
|
||||
</pre>
|
||||
<p>
|
||||
We now call <a class="link" href="../reference/basic_datagram_socket/async_send_to.html" title="basic_datagram_socket::async_send_to">ip::udp::socket::async_send_to()</a>
|
||||
to serve the data to the client.
|
||||
</p>
|
||||
<pre class="programlisting"> socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_send, this, message,
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
</pre>
|
||||
<p>
|
||||
When initiating the asynchronous operation, and if using <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a>
|
||||
, you must specify only the arguments that match the handler's parameter
|
||||
list. In this program, both of the argument placeholders (asio::placeholders::error
|
||||
and asio::placeholders::bytes_transferred) could potentially have been removed.
|
||||
</p>
|
||||
<p>
|
||||
Start listening for the next client request.
|
||||
</p>
|
||||
<pre class="programlisting"> start_receive();
|
||||
</pre>
|
||||
<p>
|
||||
Any further actions for this client request are now the responsibility of
|
||||
<code class="computeroutput">handle_send()</code>.
|
||||
</p>
|
||||
<pre class="programlisting"> }
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The function <code class="computeroutput">handle_send()</code> is invoked after the service request
|
||||
has been completed.
|
||||
</p>
|
||||
<pre class="programlisting"> void handle_send(boost::shared_ptr<std::string> /*message*/,
|
||||
const asio::error_code& /*error*/,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
}
|
||||
|
||||
udp::socket socket_;
|
||||
udp::endpoint remote_endpoint_;
|
||||
boost::array<char, 1> recv_buffer_;
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime6/src.html" title="Source listing for Daytime.6">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tutdaytime5.html" title="Daytime.5 - A synchronous UDP daytime server">Daytime.5 - A synchronous
|
||||
UDP daytime server</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tutdaytime7.html" title="Daytime.7 - A combined TCP/UDP asynchronous server">Daytime.7 - A combined TCP/UDP
|
||||
asynchronous server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime5/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime6/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,131 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.6</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="../tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">
|
||||
<link rel="prev" href="../tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">
|
||||
<link rel="next" href="../tutdaytime7.html" title="Daytime.7 - A combined TCP/UDP asynchronous server">
|
||||
</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="../tutdaytime6.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime6.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="../tutdaytime7.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime6.src"></a><a class="link" href="src.html" title="Source listing for Daytime.6">Source listing for Daytime.6</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// server.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
std::string make_daytime_string()
|
||||
{
|
||||
using namespace std; // For time_t, time and ctime;
|
||||
time_t now = time(0);
|
||||
return ctime(&now);
|
||||
}
|
||||
|
||||
class udp_server
|
||||
{
|
||||
public:
|
||||
udp_server(asio::io_context& io_context)
|
||||
: socket_(io_context, udp::endpoint(udp::v4(), 13))
|
||||
{
|
||||
start_receive();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_receive()
|
||||
{
|
||||
socket_.async_receive_from(
|
||||
asio::buffer(recv_buffer_), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_receive, this,
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void handle_receive(const asio::error_code& error,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
boost::shared_ptr<std::string> message(
|
||||
new std::string(make_daytime_string()));
|
||||
|
||||
socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_send, this, message,
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
|
||||
start_receive();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_send(boost::shared_ptr<std::string> /*message*/,
|
||||
const asio::error_code& /*error*/,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
}
|
||||
|
||||
udp::socket socket_;
|
||||
udp::endpoint remote_endpoint_;
|
||||
boost::array<char, 1> recv_buffer_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
udp_server server(io_context);
|
||||
io_context.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">Daytime.6 - An asynchronous
|
||||
UDP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime6.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime6.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="../tutdaytime7.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,220 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Daytime.7 - A combined TCP/UDP asynchronous server</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tutdaytime6/src.html" title="Source listing for Daytime.6">
|
||||
<link rel="next" href="tutdaytime7/src.html" title="Source listing for Daytime.7">
|
||||
</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="tutdaytime6/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime7/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tutdaytime7"></a><a class="link" href="tutdaytime7.html" title="Daytime.7 - A combined TCP/UDP asynchronous server">Daytime.7 - A combined TCP/UDP
|
||||
asynchronous server</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program shows how to combine the two asynchronous servers that
|
||||
we have just written, into a single server application.
|
||||
</p>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime7.h0"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime7.the_main___function"></a></span><a class="link" href="tutdaytime7.html#asio.tutorial.tutdaytime7.the_main___function">The
|
||||
main() function</a>
|
||||
</h5>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
</pre>
|
||||
<p>
|
||||
We will begin by creating a server object to accept a TCP client connection.
|
||||
</p>
|
||||
<pre class="programlisting"> tcp_server server1(io_context);
|
||||
</pre>
|
||||
<p>
|
||||
We also need a server object to accept a UDP client request.
|
||||
</p>
|
||||
<pre class="programlisting"> udp_server server2(io_context);
|
||||
</pre>
|
||||
<p>
|
||||
We have created two lots of work for the <a class="link" href="../reference/io_context.html" title="io_context">io_context</a>
|
||||
object to do.
|
||||
</p>
|
||||
<pre class="programlisting"> io_context.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime7.h1"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime7.the_tcp_connection_and_tcp_server_classes"></a></span><a class="link" href="tutdaytime7.html#asio.tutorial.tutdaytime7.the_tcp_connection_and_tcp_server_classes">The
|
||||
tcp_connection and tcp_server classes</a>
|
||||
</h5>
|
||||
<p>
|
||||
The following two classes are taken from <a class="link" href="tutdaytime3.html" title="Daytime.3 - An asynchronous TCP daytime server">Daytime.3</a>
|
||||
.
|
||||
</p>
|
||||
<pre class="programlisting">class tcp_connection
|
||||
: public boost::enable_shared_from_this<tcp_connection>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<tcp_connection> pointer;
|
||||
|
||||
static pointer create(asio::io_context& io_context)
|
||||
{
|
||||
return pointer(new tcp_connection(io_context));
|
||||
}
|
||||
|
||||
tcp::socket& socket()
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
message_ = make_daytime_string();
|
||||
|
||||
asio::async_write(socket_, asio::buffer(message_),
|
||||
boost::bind(&tcp_connection::handle_write, shared_from_this()));
|
||||
}
|
||||
|
||||
private:
|
||||
tcp_connection(asio::io_context& io_context)
|
||||
: socket_(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
void handle_write()
|
||||
{
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
class tcp_server
|
||||
{
|
||||
public:
|
||||
tcp_server(asio::io_context& io_context)
|
||||
: io_context_(io_context),
|
||||
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
|
||||
{
|
||||
start_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_accept()
|
||||
{
|
||||
tcp_connection::pointer new_connection =
|
||||
tcp_connection::create(io_context_);
|
||||
|
||||
acceptor_.async_accept(new_connection->socket(),
|
||||
boost::bind(&tcp_server::handle_accept, this, new_connection,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_accept(tcp_connection::pointer new_connection,
|
||||
const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
new_connection->start();
|
||||
}
|
||||
|
||||
start_accept();
|
||||
}
|
||||
|
||||
asio::io_context& io_context_;
|
||||
tcp::acceptor acceptor_;
|
||||
};
|
||||
</pre>
|
||||
<h5>
|
||||
<a name="asio.tutorial.tutdaytime7.h2"></a>
|
||||
<span><a name="asio.tutorial.tutdaytime7.the_udp_server_class"></a></span><a class="link" href="tutdaytime7.html#asio.tutorial.tutdaytime7.the_udp_server_class">The
|
||||
udp_server class</a>
|
||||
</h5>
|
||||
<p>
|
||||
Similarly, this next class is taken from the <a class="link" href="tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">previous
|
||||
tutorial step</a> .
|
||||
</p>
|
||||
<pre class="programlisting">class udp_server
|
||||
{
|
||||
public:
|
||||
udp_server(asio::io_context& io_context)
|
||||
: socket_(io_context, udp::endpoint(udp::v4(), 13))
|
||||
{
|
||||
start_receive();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_receive()
|
||||
{
|
||||
socket_.async_receive_from(
|
||||
asio::buffer(recv_buffer_), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_receive, this,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_receive(const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
boost::shared_ptr<std::string> message(
|
||||
new std::string(make_daytime_string()));
|
||||
|
||||
socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_send, this, message));
|
||||
|
||||
start_receive();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_send(boost::shared_ptr<std::string> /*message*/)
|
||||
{
|
||||
}
|
||||
|
||||
udp::socket socket_;
|
||||
udp::endpoint remote_endpoint_;
|
||||
boost::array<char, 1> recv_buffer_;
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tutdaytime7/src.html" title="Source listing for Daytime.7">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tutdaytime6.html" title="Daytime.6 - An asynchronous UDP daytime server">Daytime.6 - An asynchronous
|
||||
UDP daytime server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tutdaytime6/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tutdaytime7/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,202 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Daytime.7</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="../tutdaytime7.html" title="Daytime.7 - A combined TCP/UDP asynchronous server">
|
||||
<link rel="prev" href="../tutdaytime7.html" title="Daytime.7 - A combined TCP/UDP asynchronous server">
|
||||
<link rel="next" href="../boost_bind.html" title="boost::bind">
|
||||
</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="../tutdaytime7.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime7.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="../boost_bind.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tutdaytime7.src"></a><a class="link" href="src.html" title="Source listing for Daytime.7">Source listing for Daytime.7</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// server.cpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <asio.hpp>
|
||||
|
||||
using asio::ip::tcp;
|
||||
using asio::ip::udp;
|
||||
|
||||
std::string make_daytime_string()
|
||||
{
|
||||
using namespace std; // For time_t, time and ctime;
|
||||
time_t now = time(0);
|
||||
return ctime(&now);
|
||||
}
|
||||
|
||||
class tcp_connection
|
||||
: public boost::enable_shared_from_this<tcp_connection>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<tcp_connection> pointer;
|
||||
|
||||
static pointer create(asio::io_context& io_context)
|
||||
{
|
||||
return pointer(new tcp_connection(io_context));
|
||||
}
|
||||
|
||||
tcp::socket& socket()
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
message_ = make_daytime_string();
|
||||
|
||||
asio::async_write(socket_, asio::buffer(message_),
|
||||
boost::bind(&tcp_connection::handle_write, shared_from_this()));
|
||||
}
|
||||
|
||||
private:
|
||||
tcp_connection(asio::io_context& io_context)
|
||||
: socket_(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
void handle_write()
|
||||
{
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
class tcp_server
|
||||
{
|
||||
public:
|
||||
tcp_server(asio::io_context& io_context)
|
||||
: io_context_(io_context),
|
||||
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
|
||||
{
|
||||
start_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_accept()
|
||||
{
|
||||
tcp_connection::pointer new_connection =
|
||||
tcp_connection::create(io_context_);
|
||||
|
||||
acceptor_.async_accept(new_connection->socket(),
|
||||
boost::bind(&tcp_server::handle_accept, this, new_connection,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_accept(tcp_connection::pointer new_connection,
|
||||
const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
new_connection->start();
|
||||
}
|
||||
|
||||
start_accept();
|
||||
}
|
||||
|
||||
asio::io_context& io_context_;
|
||||
tcp::acceptor acceptor_;
|
||||
};
|
||||
|
||||
class udp_server
|
||||
{
|
||||
public:
|
||||
udp_server(asio::io_context& io_context)
|
||||
: socket_(io_context, udp::endpoint(udp::v4(), 13))
|
||||
{
|
||||
start_receive();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_receive()
|
||||
{
|
||||
socket_.async_receive_from(
|
||||
asio::buffer(recv_buffer_), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_receive, this,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_receive(const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
boost::shared_ptr<std::string> message(
|
||||
new std::string(make_daytime_string()));
|
||||
|
||||
socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
|
||||
boost::bind(&udp_server::handle_send, this, message));
|
||||
|
||||
start_receive();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_send(boost::shared_ptr<std::string> /*message*/)
|
||||
{
|
||||
}
|
||||
|
||||
udp::socket socket_;
|
||||
udp::endpoint remote_endpoint_;
|
||||
boost::array<char, 1> recv_buffer_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
asio::io_context io_context;
|
||||
tcp_server server1(io_context);
|
||||
udp_server server2(io_context);
|
||||
io_context.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tutdaytime7.html" title="Daytime.7 - A combined TCP/UDP asynchronous server">Daytime.7 - A combined
|
||||
TCP/UDP asynchronous server</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutdaytime7.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutdaytime7.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="../boost_bind.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,103 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Timer.1 - Using a timer synchronously</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="../tutorial.html" title="Tutorial">
|
||||
<link rel="next" href="tuttimer1/src.html" title="Source listing for Timer.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="../tutorial.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer1/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tuttimer1"></a><a class="link" href="tuttimer1.html" title="Timer.1 - Using a timer synchronously">Timer.1 - Using a timer synchronously</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program introduces asio by showing how to perform a blocking
|
||||
wait on a timer.
|
||||
</p>
|
||||
<p>
|
||||
We start by including the necessary header files.
|
||||
</p>
|
||||
<p>
|
||||
All of the asio classes can be used by simply including the <code class="computeroutput">"asio.hpp"</code>
|
||||
header file.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <asio.hpp>
|
||||
</pre>
|
||||
<p>
|
||||
All programs that use asio need to have at least one I/O execution context,
|
||||
such as an <a class="link" href="../reference/io_context.html" title="io_context">io_context</a> or
|
||||
<a class="link" href="../reference/thread_pool.html" title="thread_pool">thread_pool</a> object. An
|
||||
I/O execution context provides access to I/O functionality. We declare an
|
||||
object of type <a class="link" href="../reference/io_context.html" title="io_context">io_context</a>
|
||||
first thing in the main function.
|
||||
</p>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
</pre>
|
||||
<p>
|
||||
Next we declare an object of type asio::steady_timer. The core asio classes
|
||||
that provide I/O functionality (or as in this case timer functionality) always
|
||||
take a reference to an io_context as their first constructor argument. The
|
||||
second argument to the constructor sets the timer to expire 5 seconds from
|
||||
now.
|
||||
</p>
|
||||
<pre class="programlisting"> asio::steady_timer t(io, asio::chrono::seconds(5));
|
||||
</pre>
|
||||
<p>
|
||||
In this simple example we perform a blocking wait on the timer. That is,
|
||||
the call to <a class="link" href="../reference/basic_waitable_timer/wait.html" title="basic_waitable_timer::wait">steady_timer::wait()</a>
|
||||
will not return until the timer has expired, 5 seconds after it was created
|
||||
(i.e. not from when the wait starts).
|
||||
</p>
|
||||
<p>
|
||||
A timer is always in one of two states: "expired" or "not
|
||||
expired". If the <a class="link" href="../reference/basic_waitable_timer/wait.html" title="basic_waitable_timer::wait">steady_timer::wait()</a>
|
||||
function is called on an expired timer, it will return immediately.
|
||||
</p>
|
||||
<pre class="programlisting"> t.wait();
|
||||
</pre>
|
||||
<p>
|
||||
Finally we print the obligatory <code class="computeroutput">"Hello, world!"</code> message
|
||||
to show when the timer has expired.
|
||||
</p>
|
||||
<pre class="programlisting"> std::cout << "Hello, world!" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tuttimer1/src.html" title="Source listing for Timer.1">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tuttimer2.html" title="Timer.2 - Using a timer asynchronously">Timer.2 - Using a timer asynchronously</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tutorial.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer1/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,66 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Timer.1</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="../tuttimer1.html" title="Timer.1 - Using a timer synchronously">
|
||||
<link rel="prev" href="../tuttimer1.html" title="Timer.1 - Using a timer synchronously">
|
||||
<link rel="next" href="../tuttimer2.html" title="Timer.2 - Using a timer asynchronously">
|
||||
</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="../tuttimer1.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer1.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="../tuttimer2.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tuttimer1.src"></a><a class="link" href="src.html" title="Source listing for Timer.1">Source listing for Timer.1</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// timer.cpp
|
||||
// ~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <asio.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
|
||||
asio::steady_timer t(io, asio::chrono::seconds(5));
|
||||
t.wait();
|
||||
|
||||
std::cout << "Hello, world!" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tuttimer1.html" title="Timer.1 - Using a timer synchronously">Timer.1 - Using a timer
|
||||
synchronously</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tuttimer1.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer1.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="../tuttimer2.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,114 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Timer.2 - Using a timer asynchronously</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tuttimer1/src.html" title="Source listing for Timer.1">
|
||||
<link rel="next" href="tuttimer2/src.html" title="Source listing for Timer.2">
|
||||
</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="tuttimer1/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer2/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tuttimer2"></a><a class="link" href="tuttimer2.html" title="Timer.2 - Using a timer asynchronously">Timer.2 - Using a timer asynchronously</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial program demonstrates how to use asio's asynchronous callback
|
||||
functionality by modifying the program from tutorial Timer.1 to perform an
|
||||
asynchronous wait on the timer.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <asio.hpp>
|
||||
</pre>
|
||||
<p>
|
||||
Using asio's asynchronous functionality means having a callback function
|
||||
that will be called when an asynchronous operation completes. In this program
|
||||
we define a function called <code class="computeroutput">print</code> to be called when the asynchronous
|
||||
wait finishes.
|
||||
</p>
|
||||
<pre class="programlisting">void print(const asio::error_code& /*e*/)
|
||||
{
|
||||
std::cout << "Hello, world!" << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
|
||||
asio::steady_timer t(io, asio::chrono::seconds(5));
|
||||
</pre>
|
||||
<p>
|
||||
Next, instead of doing a blocking wait as in tutorial Timer.1, we call the
|
||||
<a class="link" href="../reference/basic_waitable_timer/async_wait.html" title="basic_waitable_timer::async_wait">steady_timer::async_wait()</a>
|
||||
function to perform an asynchronous wait. When calling this function we pass
|
||||
the <code class="computeroutput">print</code> callback handler that was defined above.
|
||||
</p>
|
||||
<pre class="programlisting"> t.async_wait(&print);
|
||||
</pre>
|
||||
<p>
|
||||
Finally, we must call the <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
member function on the io_context object.
|
||||
</p>
|
||||
<p>
|
||||
The asio library provides a guarantee that callback handlers will only be
|
||||
called from threads that are currently calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
|
||||
Therefore unless the <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
function is called the callback for the asynchronous wait completion will
|
||||
never be invoked.
|
||||
</p>
|
||||
<p>
|
||||
The <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
function will also continue to run while there is still "work"
|
||||
to do. In this example, the work is the asynchronous wait on the timer, so
|
||||
the call will not return until the timer has expired and the callback has
|
||||
completed.
|
||||
</p>
|
||||
<p>
|
||||
It is important to remember to give the io_context some work to do before
|
||||
calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
|
||||
For example, if we had omitted the above call to <a class="link" href="../reference/basic_waitable_timer/async_wait.html" title="basic_waitable_timer::async_wait">steady_timer::async_wait()</a>,
|
||||
the io_context would not have had any work to do, and consequently <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a> would have
|
||||
returned immediately.
|
||||
</p>
|
||||
<pre class="programlisting"> io.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tuttimer2/src.html" title="Source listing for Timer.2">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tuttimer1.html" title="Timer.1 - Using a timer synchronously">Timer.1 - Using a timer
|
||||
synchronously</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tuttimer3.html" title="Timer.3 - Binding arguments to a handler">Timer.3 - Binding arguments
|
||||
to a handler</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tuttimer1/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer2/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,71 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Timer.2</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="../tuttimer2.html" title="Timer.2 - Using a timer asynchronously">
|
||||
<link rel="prev" href="../tuttimer2.html" title="Timer.2 - Using a timer asynchronously">
|
||||
<link rel="next" href="../tuttimer3.html" title="Timer.3 - Binding arguments to a handler">
|
||||
</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="../tuttimer2.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer2.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="../tuttimer3.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tuttimer2.src"></a><a class="link" href="src.html" title="Source listing for Timer.2">Source listing for Timer.2</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// timer.cpp
|
||||
// ~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <asio.hpp>
|
||||
|
||||
void print(const asio::error_code& /*e*/)
|
||||
{
|
||||
std::cout << "Hello, world!" << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
|
||||
asio::steady_timer t(io, asio::chrono::seconds(5));
|
||||
t.async_wait(&print);
|
||||
|
||||
io.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tuttimer2.html" title="Timer.2 - Using a timer asynchronously">Timer.2 - Using a timer
|
||||
asynchronously</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tuttimer2.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer2.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="../tuttimer3.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,160 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Timer.3 - Binding arguments to a handler</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tuttimer2/src.html" title="Source listing for Timer.2">
|
||||
<link rel="next" href="tuttimer3/src.html" title="Source listing for Timer.3">
|
||||
</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="tuttimer2/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer3/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tuttimer3"></a><a class="link" href="tuttimer3.html" title="Timer.3 - Binding arguments to a handler">Timer.3 - Binding arguments
|
||||
to a handler</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
In this tutorial we will modify the program from tutorial Timer.2 so that
|
||||
the timer fires once a second. This will show how to pass additional parameters
|
||||
to your handler function.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
</pre>
|
||||
<p>
|
||||
To implement a repeating timer using asio you need to change the timer's
|
||||
expiry time in your callback function, and to then start a new asynchronous
|
||||
wait. Obviously this means that the callback function will need to be able
|
||||
to access the timer object. To this end we add two new parameters to the
|
||||
<code class="computeroutput">print</code> function:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
A pointer to a timer object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
A counter so that we can stop the program when the timer fires for the
|
||||
sixth time.
|
||||
</li>
|
||||
</ul></div>
|
||||
<pre class="programlisting">void print(const asio::error_code& /*e*/,
|
||||
asio::steady_timer* t, int* count)
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
As mentioned above, this tutorial program uses a counter to stop running
|
||||
when the timer fires for the sixth time. However you will observe that there
|
||||
is no explicit call to ask the io_context to stop. Recall that in tutorial
|
||||
Timer.2 we learnt that the <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
function completes when there is no more "work" to do. By not starting
|
||||
a new asynchronous wait on the timer when <code class="computeroutput">count</code> reaches 5, the
|
||||
io_context will run out of work and stop running.
|
||||
</p>
|
||||
<pre class="programlisting"> if (*count < 5)
|
||||
{
|
||||
std::cout << *count << std::endl;
|
||||
++(*count);
|
||||
</pre>
|
||||
<p>
|
||||
Next we move the expiry time for the timer along by one second from the previous
|
||||
expiry time. By calculating the new expiry time relative to the old, we can
|
||||
ensure that the timer does not drift away from the whole-second mark due
|
||||
to any delays in processing the handler.
|
||||
</p>
|
||||
<pre class="programlisting"> t->expires_at(t->expiry() + asio::chrono::seconds(1));
|
||||
</pre>
|
||||
<p>
|
||||
Then we start a new asynchronous wait on the timer. As you can see, the
|
||||
<a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a> function is used
|
||||
to associate the extra parameters with your callback handler. The <a class="link" href="../reference/basic_waitable_timer/async_wait.html" title="basic_waitable_timer::async_wait">steady_timer::async_wait()</a>
|
||||
function expects a handler function (or function object) with the signature
|
||||
<code class="computeroutput">void(const asio::error_code&)</code>. Binding the additional parameters
|
||||
converts your <code class="computeroutput">print</code> function into a function object that matches
|
||||
the signature correctly.
|
||||
</p>
|
||||
<p>
|
||||
See the <a href="http://www.boost.org/libs/bind/bind.html" target="_top">Boost.Bind
|
||||
documentation</a> for more information on how to use <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
In this example, the asio::placeholders::error argument to <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a>
|
||||
is a named placeholder for the error object passed to the handler. When initiating
|
||||
the asynchronous operation, and if using <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a>
|
||||
, you must specify only the arguments that match the handler's parameter
|
||||
list. In tutorial Timer.4 you will see that this placeholder may be elided
|
||||
if the parameter is not needed by the callback handler.
|
||||
</p>
|
||||
<pre class="programlisting"> t->async_wait(boost::bind(print,
|
||||
asio::placeholders::error, t, count));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
</pre>
|
||||
<p>
|
||||
A new <code class="computeroutput">count</code> variable is added so that we can stop the program
|
||||
when the timer fires for the sixth time.
|
||||
</p>
|
||||
<pre class="programlisting"> int count = 0;
|
||||
asio::steady_timer t(io, asio::chrono::seconds(1));
|
||||
</pre>
|
||||
<p>
|
||||
As in Step 4, when making the call to <a class="link" href="../reference/basic_waitable_timer/async_wait.html" title="basic_waitable_timer::async_wait">steady_timer::async_wait()</a>
|
||||
from <code class="computeroutput">main</code> we bind the additional parameters needed for the
|
||||
<code class="computeroutput">print</code> function.
|
||||
</p>
|
||||
<pre class="programlisting"> t.async_wait(boost::bind(print,
|
||||
asio::placeholders::error, &t, &count));
|
||||
|
||||
io.run();
|
||||
</pre>
|
||||
<p>
|
||||
Finally, just to prove that the <code class="computeroutput">count</code> variable was being used
|
||||
in the <code class="computeroutput">print</code> handler function, we will print out its new value.
|
||||
</p>
|
||||
<pre class="programlisting"> std::cout << "Final count is " << count << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tuttimer3/src.html" title="Source listing for Timer.3">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tuttimer2.html" title="Timer.2 - Using a timer asynchronously">Timer.2 - Using a timer
|
||||
asynchronously</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tuttimer4.html" title="Timer.4 - Using a member function as a handler">Timer.4 - Using a member function
|
||||
as a handler</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tuttimer2/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer3/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,85 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Timer.3</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="../tuttimer3.html" title="Timer.3 - Binding arguments to a handler">
|
||||
<link rel="prev" href="../tuttimer3.html" title="Timer.3 - Binding arguments to a handler">
|
||||
<link rel="next" href="../tuttimer4.html" title="Timer.4 - Using a member function as a handler">
|
||||
</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="../tuttimer3.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer3.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="../tuttimer4.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tuttimer3.src"></a><a class="link" href="src.html" title="Source listing for Timer.3">Source listing for Timer.3</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// timer.cpp
|
||||
// ~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
void print(const asio::error_code& /*e*/,
|
||||
asio::steady_timer* t, int* count)
|
||||
{
|
||||
if (*count < 5)
|
||||
{
|
||||
std::cout << *count << std::endl;
|
||||
++(*count);
|
||||
|
||||
t->expires_at(t->expiry() + asio::chrono::seconds(1));
|
||||
t->async_wait(boost::bind(print,
|
||||
asio::placeholders::error, t, count));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
|
||||
int count = 0;
|
||||
asio::steady_timer t(io, asio::chrono::seconds(1));
|
||||
t.async_wait(boost::bind(print,
|
||||
asio::placeholders::error, &t, &count));
|
||||
|
||||
io.run();
|
||||
|
||||
std::cout << "Final count is " << count << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tuttimer3.html" title="Timer.3 - Binding arguments to a handler">Timer.3 - Binding arguments
|
||||
to a handler</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tuttimer3.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer3.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="../tuttimer4.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,140 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Timer.4 - Using a member function as a handler</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tuttimer3/src.html" title="Source listing for Timer.3">
|
||||
<link rel="next" href="tuttimer4/src.html" title="Source listing for Timer.4">
|
||||
</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="tuttimer3/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer4/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tuttimer4"></a><a class="link" href="tuttimer4.html" title="Timer.4 - Using a member function as a handler">Timer.4 - Using a member function
|
||||
as a handler</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
In this tutorial we will see how to use a class member function as a callback
|
||||
handler. The program should execute identically to the tutorial program from
|
||||
tutorial Timer.3.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
</pre>
|
||||
<p>
|
||||
Instead of defining a free function <code class="computeroutput">print</code> as the callback handler,
|
||||
as we did in the earlier tutorial programs, we now define a class called
|
||||
<code class="computeroutput">printer</code>.
|
||||
</p>
|
||||
<pre class="programlisting">class printer
|
||||
{
|
||||
public:
|
||||
</pre>
|
||||
<p>
|
||||
The constructor of this class will take a reference to the io_context object
|
||||
and use it when initialising the <code class="computeroutput">timer_</code> member. The counter
|
||||
used to shut down the program is now also a member of the class.
|
||||
</p>
|
||||
<pre class="programlisting"> printer(asio::io_context& io)
|
||||
: timer_(io, asio::chrono::seconds(1)),
|
||||
count_(0)
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
The <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a> function
|
||||
works just as well with class member functions as with free functions. Since
|
||||
all non-static class member functions have an implicit <code class="computeroutput">this</code>
|
||||
parameter, we need to bind <code class="computeroutput">this</code> to the function. As in tutorial
|
||||
Timer.3, <a class="link" href="boost_bind.html" title="boost::bind">boost::bind</a> converts
|
||||
our callback handler (now a member function) into a function object that
|
||||
can be invoked as though it has the signature <code class="computeroutput">void(const asio::error_code&)</code>.
|
||||
</p>
|
||||
<p>
|
||||
You will note that the asio::placeholders::error placeholder is not specified
|
||||
here, as the <code class="computeroutput">print</code> member function does not accept an error
|
||||
object as a parameter.
|
||||
</p>
|
||||
<pre class="programlisting"> timer_.async_wait(boost::bind(&printer::print, this));
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
In the class destructor we will print out the final value of the counter.
|
||||
</p>
|
||||
<pre class="programlisting"> ~printer()
|
||||
{
|
||||
std::cout << "Final count is " << count_ << std::endl;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput">print</code> member function is very similar to the <code class="computeroutput">print</code>
|
||||
function from tutorial Timer.3, except that it now operates on the class
|
||||
data members instead of having the timer and counter passed in as parameters.
|
||||
</p>
|
||||
<pre class="programlisting"> void print()
|
||||
{
|
||||
if (count_ < 5)
|
||||
{
|
||||
std::cout << count_ << std::endl;
|
||||
++count_;
|
||||
|
||||
timer_.expires_at(timer_.expiry() + asio::chrono::seconds(1));
|
||||
timer_.async_wait(boost::bind(&printer::print, this));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
asio::steady_timer timer_;
|
||||
int count_;
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput">main</code> function is much simpler than before, as it now declares
|
||||
a local <code class="computeroutput">printer</code> object before running the io_context as normal.
|
||||
</p>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
printer p(io);
|
||||
io.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tuttimer4/src.html" title="Source listing for Timer.4">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tuttimer3.html" title="Timer.3 - Binding arguments to a handler">Timer.3 - Binding arguments
|
||||
to a handler</a>
|
||||
</p>
|
||||
<p>
|
||||
Next: <a class="link" href="tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">Timer.5 - Synchronising handlers
|
||||
in multithreaded programs</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tuttimer3/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer4/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,96 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Timer.4</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="../tuttimer4.html" title="Timer.4 - Using a member function as a handler">
|
||||
<link rel="prev" href="../tuttimer4.html" title="Timer.4 - Using a member function as a handler">
|
||||
<link rel="next" href="../tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">
|
||||
</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="../tuttimer4.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer4.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="../tuttimer5.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tuttimer4.src"></a><a class="link" href="src.html" title="Source listing for Timer.4">Source listing for Timer.4</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// timer.cpp
|
||||
// ~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
class printer
|
||||
{
|
||||
public:
|
||||
printer(asio::io_context& io)
|
||||
: timer_(io, asio::chrono::seconds(1)),
|
||||
count_(0)
|
||||
{
|
||||
timer_.async_wait(boost::bind(&printer::print, this));
|
||||
}
|
||||
|
||||
~printer()
|
||||
{
|
||||
std::cout << "Final count is " << count_ << std::endl;
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
if (count_ < 5)
|
||||
{
|
||||
std::cout << count_ << std::endl;
|
||||
++count_;
|
||||
|
||||
timer_.expires_at(timer_.expiry() + asio::chrono::seconds(1));
|
||||
timer_.async_wait(boost::bind(&printer::print, this));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
asio::steady_timer timer_;
|
||||
int count_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
printer p(io);
|
||||
io.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tuttimer4.html" title="Timer.4 - Using a member function as a handler">Timer.4 - Using a member
|
||||
function as a handler</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tuttimer4.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer4.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="../tuttimer5.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,199 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Timer.5 - Synchronising handlers in multithreaded programs</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="../tutorial.html" title="Tutorial">
|
||||
<link rel="prev" href="tuttimer4/src.html" title="Source listing for Timer.4">
|
||||
<link rel="next" href="tuttimer5/src.html" title="Source listing for Timer.5">
|
||||
</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="tuttimer4/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer5/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="asio.tutorial.tuttimer5"></a><a class="link" href="tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">Timer.5 - Synchronising handlers
|
||||
in multithreaded programs</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
This tutorial demonstrates the use of the <a class="link" href="../reference/strand.html" title="strand">strand</a>
|
||||
class template to synchronise callback handlers in a multithreaded program.
|
||||
</p>
|
||||
<p>
|
||||
The previous four tutorials avoided the issue of handler synchronisation
|
||||
by calling the <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
function from one thread only. As you already know, the asio library provides
|
||||
a guarantee that callback handlers will only be called from threads that
|
||||
are currently calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
|
||||
Consequently, calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
from only one thread ensures that callback handlers cannot run concurrently.
|
||||
</p>
|
||||
<p>
|
||||
The single threaded approach is usually the best place to start when developing
|
||||
applications using asio. The downside is the limitations it places on programs,
|
||||
particularly servers, including:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
Poor responsiveness when handlers can take a long time to complete.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
An inability to scale on multiprocessor systems.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
If you find yourself running into these limitations, an alternative approach
|
||||
is to have a pool of threads calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
|
||||
However, as this allows handlers to execute concurrently, we need a method
|
||||
of synchronisation when handlers might be accessing a shared, thread-unsafe
|
||||
resource.
|
||||
</p>
|
||||
<pre class="programlisting">#include <iostream>
|
||||
#include <asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
</pre>
|
||||
<p>
|
||||
We start by defining a class called <code class="computeroutput">printer</code>, similar to the
|
||||
class in the previous tutorial. This class will extend the previous tutorial
|
||||
by running two timers in parallel.
|
||||
</p>
|
||||
<pre class="programlisting">class printer
|
||||
{
|
||||
public:
|
||||
</pre>
|
||||
<p>
|
||||
In addition to initialising a pair of asio::steady_timer members, the constructor
|
||||
initialises the <code class="computeroutput">strand_</code> member, an object of type asio::strand<asio::io_context::executor_type>.
|
||||
</p>
|
||||
<p>
|
||||
The <a class="link" href="../reference/strand.html" title="strand">strand</a> class template is
|
||||
an executor adapter that guarantees that, for those handlers that are dispatched
|
||||
through it, an executing handler will be allowed to complete before the next
|
||||
one is started. This is guaranteed irrespective of the number of threads
|
||||
that are calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
|
||||
Of course, the handlers may still execute concurrently with other handlers
|
||||
that were not dispatched through an <a class="link" href="../reference/strand.html" title="strand">strand</a>,
|
||||
or were dispatched through a different <a class="link" href="../reference/strand.html" title="strand">strand</a>
|
||||
object.
|
||||
</p>
|
||||
<pre class="programlisting"> printer(asio::io_context& io)
|
||||
: strand_(asio::make_strand(io)),
|
||||
timer1_(io, asio::chrono::seconds(1)),
|
||||
timer2_(io, asio::chrono::seconds(1)),
|
||||
count_(0)
|
||||
{
|
||||
</pre>
|
||||
<p>
|
||||
When initiating the asynchronous operations, each callback handler is "bound"
|
||||
to an asio::strand<asio::io_context::executor_type> object. The asio::bind_executor()
|
||||
function returns a new handler that automatically dispatches its contained
|
||||
handler through the <a class="link" href="../reference/strand.html" title="strand">strand</a> object.
|
||||
By binding the handlers to the same <a class="link" href="../reference/strand.html" title="strand">strand</a>,
|
||||
we are ensuring that they cannot execute concurrently.
|
||||
</p>
|
||||
<pre class="programlisting"> timer1_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print1, this)));
|
||||
|
||||
timer2_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print2, this)));
|
||||
}
|
||||
|
||||
~printer()
|
||||
{
|
||||
std::cout << "Final count is " << count_ << std::endl;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
In a multithreaded program, the handlers for asynchronous operations should
|
||||
be synchronised if they access shared resources. In this tutorial, the shared
|
||||
resources used by the handlers (<code class="computeroutput">print1</code> and <code class="computeroutput">print2</code>)
|
||||
are <code class="computeroutput">std::cout</code> and the <code class="computeroutput">count_</code> data member.
|
||||
</p>
|
||||
<pre class="programlisting"> void print1()
|
||||
{
|
||||
if (count_ < 10)
|
||||
{
|
||||
std::cout << "Timer 1: " << count_ << std::endl;
|
||||
++count_;
|
||||
|
||||
timer1_.expires_at(timer1_.expiry() + asio::chrono::seconds(1));
|
||||
|
||||
timer1_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print1, this)));
|
||||
}
|
||||
}
|
||||
|
||||
void print2()
|
||||
{
|
||||
if (count_ < 10)
|
||||
{
|
||||
std::cout << "Timer 2: " << count_ << std::endl;
|
||||
++count_;
|
||||
|
||||
timer2_.expires_at(timer2_.expiry() + asio::chrono::seconds(1));
|
||||
|
||||
timer2_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print2, this)));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
asio::strand<asio::io_context::executor_type> strand_;
|
||||
asio::steady_timer timer1_;
|
||||
asio::steady_timer timer2_;
|
||||
int count_;
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput">main</code> function now causes <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
|
||||
to be called from two threads: the main thread and one additional thread.
|
||||
This is accomplished using an <a class="link" href="../reference/thread.html" title="thread">thread</a>
|
||||
object.
|
||||
</p>
|
||||
<p>
|
||||
Just as it would with a call from a single thread, concurrent calls to <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a> will continue
|
||||
to execute while there is "work" left to do. The background thread
|
||||
will not exit until all asynchronous operations have completed.
|
||||
</p>
|
||||
<pre class="programlisting">int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
printer p(io);
|
||||
asio::thread t(boost::bind(&asio::io_context::run, &io));
|
||||
io.run();
|
||||
t.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
See the <a class="link" href="tuttimer5/src.html" title="Source listing for Timer.5">full source listing</a>
|
||||
</p>
|
||||
<p>
|
||||
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
|
||||
</p>
|
||||
<p>
|
||||
Previous: <a class="link" href="tuttimer4.html" title="Timer.4 - Using a member function as a handler">Timer.4 - Using a member
|
||||
function as a handler</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="tuttimer4/src.html"><img src="../../prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.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="tuttimer5/src.html"><img src="../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,122 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Source listing for Timer.5</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="../tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">
|
||||
<link rel="prev" href="../tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">
|
||||
<link rel="next" href="../tutdaytime1.html" title="Daytime.1 - A synchronous TCP daytime client">
|
||||
</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="../tuttimer5.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer5.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="../tutdaytime1.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.tutorial.tuttimer5.src"></a><a class="link" href="src.html" title="Source listing for Timer.5">Source listing for Timer.5</a>
|
||||
</h4></div></div></div>
|
||||
<pre class="programlisting">//
|
||||
// timer.cpp
|
||||
// ~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2020 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)
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
class printer
|
||||
{
|
||||
public:
|
||||
printer(asio::io_context& io)
|
||||
: strand_(asio::make_strand(io)),
|
||||
timer1_(io, asio::chrono::seconds(1)),
|
||||
timer2_(io, asio::chrono::seconds(1)),
|
||||
count_(0)
|
||||
{
|
||||
timer1_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print1, this)));
|
||||
|
||||
timer2_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print2, this)));
|
||||
}
|
||||
|
||||
~printer()
|
||||
{
|
||||
std::cout << "Final count is " << count_ << std::endl;
|
||||
}
|
||||
|
||||
void print1()
|
||||
{
|
||||
if (count_ < 10)
|
||||
{
|
||||
std::cout << "Timer 1: " << count_ << std::endl;
|
||||
++count_;
|
||||
|
||||
timer1_.expires_at(timer1_.expiry() + asio::chrono::seconds(1));
|
||||
|
||||
timer1_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print1, this)));
|
||||
}
|
||||
}
|
||||
|
||||
void print2()
|
||||
{
|
||||
if (count_ < 10)
|
||||
{
|
||||
std::cout << "Timer 2: " << count_ << std::endl;
|
||||
++count_;
|
||||
|
||||
timer2_.expires_at(timer2_.expiry() + asio::chrono::seconds(1));
|
||||
|
||||
timer2_.async_wait(asio::bind_executor(strand_,
|
||||
boost::bind(&printer::print2, this)));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
asio::strand<asio::io_context::executor_type> strand_;
|
||||
asio::steady_timer timer1_;
|
||||
asio::steady_timer timer2_;
|
||||
int count_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
asio::io_context io;
|
||||
printer p(io);
|
||||
asio::thread t(boost::bind(&asio::io_context::run, &io));
|
||||
io.run();
|
||||
t.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Return to <a class="link" href="../tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">Timer.5 - Synchronising
|
||||
handlers in multithreaded programs</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 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></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../tuttimer5.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../tuttimer5.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="../tutdaytime1.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user