summaryrefslogtreecommitdiff
path: root/doc/html/boost_asio/tutorial/tutdaytime3.html
blob: bafe29840d3c6ad92626f4eff296618c8a88d557 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Daytime.3 - An asynchronous TCP daytime server</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../../boost_asio.html" title="Boost.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="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="tutdaytime2/src.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tutdaytime3/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_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="boost_asio.tutorial.tutdaytime3.h0"></a>
        <span class="phrase"><a name="boost_asio.tutorial.tutdaytime3.the_main___function"></a></span><a class="link" href="tutdaytime3.html#boost_asio.tutorial.tutdaytime3.the_main___function">The
        main() function</a>
      </h5>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
  <span class="keyword">try</span>
  <span class="special">{</span>
</pre>
<p>
        We need to create a server object to accept incoming client connections.
        The <a class="link" href="../reference/io_service.html" title="io_service">io_service</a> object
        provides I/O services, such as sockets, that the server object will use.
      </p>
<pre class="programlisting">    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_service</span> <span class="identifier">io_service</span><span class="special">;</span>
    <span class="identifier">tcp_server</span> <span class="identifier">server</span><span class="special">(</span><span class="identifier">io_service</span><span class="special">);</span>
</pre>
<p>
        Run the <a class="link" href="../reference/io_service.html" title="io_service">io_service</a>
        object so that it will perform asynchronous operations on your behalf.
      </p>
<pre class="programlisting">    <span class="identifier">io_service</span><span class="special">.</span><span class="identifier">run</span><span class="special">();</span>
  <span class="special">}</span>
  <span class="keyword">catch</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span><span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span>
  <span class="special">{</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
  <span class="special">}</span>

  <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<h5>
<a name="boost_asio.tutorial.tutdaytime3.h1"></a>
        <span class="phrase"><a name="boost_asio.tutorial.tutdaytime3.the_tcp_server_class"></a></span><a class="link" href="tutdaytime3.html#boost_asio.tutorial.tutdaytime3.the_tcp_server_class">The tcp_server
        class</a>
      </h5>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">tcp_server</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
</pre>
<p>
        The constructor initialises an acceptor to listen on TCP port 13.
      </p>
<pre class="programlisting">  <span class="identifier">tcp_server</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_service</span><span class="special">&amp;</span> <span class="identifier">io_service</span><span class="special">)</span>
    <span class="special">:</span> <span class="identifier">acceptor_</span><span class="special">(</span><span class="identifier">io_service</span><span class="special">,</span> <span class="identifier">tcp</span><span class="special">::</span><span class="identifier">endpoint</span><span class="special">(</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">v4</span><span class="special">(),</span> <span class="number">13</span><span class="special">))</span>
  <span class="special">{</span>
    <span class="identifier">start_accept</span><span class="special">();</span>
  <span class="special">}</span>

<span class="keyword">private</span><span class="special">:</span>
</pre>
<p>
        The function <code class="computeroutput"><span class="identifier">start_accept</span><span class="special">()</span></code> creates a socket and initiates an asynchronous
        accept operation to wait for a new connection.
      </p>
<pre class="programlisting">  <span class="keyword">void</span> <span class="identifier">start_accept</span><span class="special">()</span>
  <span class="special">{</span>
    <span class="identifier">tcp_connection</span><span class="special">::</span><span class="identifier">pointer</span> <span class="identifier">new_connection</span> <span class="special">=</span>
      <span class="identifier">tcp_connection</span><span class="special">::</span><span class="identifier">create</span><span class="special">(</span><span class="identifier">acceptor_</span><span class="special">.</span><span class="identifier">get_io_service</span><span class="special">());</span>

    <span class="identifier">acceptor_</span><span class="special">.</span><span class="identifier">async_accept</span><span class="special">(</span><span class="identifier">new_connection</span><span class="special">-&gt;</span><span class="identifier">socket</span><span class="special">(),</span>
        <span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">tcp_server</span><span class="special">::</span><span class="identifier">handle_accept</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span> <span class="identifier">new_connection</span><span class="special">,</span>
          <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">placeholders</span><span class="special">::</span><span class="identifier">error</span><span class="special">));</span>
  <span class="special">}</span>
</pre>
<p>
        The function <code class="computeroutput"><span class="identifier">handle_accept</span><span class="special">()</span></code> is called when the asynchronous accept
        operation initiated by <code class="computeroutput"><span class="identifier">start_accept</span><span class="special">()</span></code> finishes. It services the client request,
        and then calls <code class="computeroutput"><span class="identifier">start_accept</span><span class="special">()</span></code> to initiate the next accept operation.
      </p>
<pre class="programlisting">  <span class="keyword">void</span> <span class="identifier">handle_accept</span><span class="special">(</span><span class="identifier">tcp_connection</span><span class="special">::</span><span class="identifier">pointer</span> <span class="identifier">new_connection</span><span class="special">,</span>
      <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">&amp;</span> <span class="identifier">error</span><span class="special">)</span>
  <span class="special">{</span>
    <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">error</span><span class="special">)</span>
    <span class="special">{</span>
      <span class="identifier">new_connection</span><span class="special">-&gt;</span><span class="identifier">start</span><span class="special">();</span>
    <span class="special">}</span>

    <span class="identifier">start_accept</span><span class="special">();</span>
  <span class="special">}</span>
</pre>
<h5>
<a name="boost_asio.tutorial.tutdaytime3.h2"></a>
        <span class="phrase"><a name="boost_asio.tutorial.tutdaytime3.the_tcp_connection_class"></a></span><a class="link" href="tutdaytime3.html#boost_asio.tutorial.tutdaytime3.the_tcp_connection_class">The tcp_connection
        class</a>
      </h5>
<p>
        We will use <code class="computeroutput"><span class="identifier">shared_ptr</span></code> and
        <code class="computeroutput"><span class="identifier">enable_shared_from_this</span></code> because
        we want to keep the <code class="computeroutput"><span class="identifier">tcp_connection</span></code>
        object alive as long as there is an operation that refers to it.
      </p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">tcp_connection</span>
  <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">enable_shared_from_this</span><span class="special">&lt;</span><span class="identifier">tcp_connection</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
  <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span><span class="identifier">tcp_connection</span><span class="special">&gt;</span> <span class="identifier">pointer</span><span class="special">;</span>

  <span class="keyword">static</span> <span class="identifier">pointer</span> <span class="identifier">create</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_service</span><span class="special">&amp;</span> <span class="identifier">io_service</span><span class="special">)</span>
  <span class="special">{</span>
    <span class="keyword">return</span> <span class="identifier">pointer</span><span class="special">(</span><span class="keyword">new</span> <span class="identifier">tcp_connection</span><span class="special">(</span><span class="identifier">io_service</span><span class="special">));</span>
  <span class="special">}</span>

  <span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span><span class="special">&amp;</span> <span class="identifier">socket</span><span class="special">()</span>
  <span class="special">{</span>
    <span class="keyword">return</span> <span class="identifier">socket_</span><span class="special">;</span>
  <span class="special">}</span>
</pre>
<p>
        In the function <code class="computeroutput"><span class="identifier">start</span><span class="special">()</span></code>,
        we call boost::asio::async_write() to serve the data to the client. Note
        that we are using boost::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">  <span class="keyword">void</span> <span class="identifier">start</span><span class="special">()</span>
  <span class="special">{</span>
</pre>
<p>
        The data to be sent is stored in the class member <code class="computeroutput"><span class="identifier">message_</span></code>
        as we need to keep the data valid until the asynchronous operation is complete.
      </p>
<pre class="programlisting">    <span class="identifier">message_</span> <span class="special">=</span> <span class="identifier">make_daytime_string</span><span class="special">();</span>
</pre>
<p>
        When initiating the asynchronous operation, and if using boost::bind(), you
        must specify only the arguments that match the handler's parameter list.
        In this program, both of the argument placeholders (boost::asio::placeholders::error
        and boost::asio::placeholders::bytes_transferred) could potentially have
        been removed, since they are not being used in <code class="computeroutput"><span class="identifier">handle_write</span><span class="special">()</span></code>.
      </p>
<pre class="programlisting">    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">socket_</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">message_</span><span class="special">),</span>
        <span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">tcp_connection</span><span class="special">::</span><span class="identifier">handle_write</span><span class="special">,</span> <span class="identifier">shared_from_this</span><span class="special">(),</span>
          <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">placeholders</span><span class="special">::</span><span class="identifier">error</span><span class="special">,</span>
          <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">placeholders</span><span class="special">::</span><span class="identifier">bytes_transferred</span><span class="special">));</span>
</pre>
<p>
        Any further actions for this client connection are now the responsibility
        of <code class="computeroutput"><span class="identifier">handle_write</span><span class="special">()</span></code>.
      </p>
<pre class="programlisting">  <span class="special">}</span>

<span class="keyword">private</span><span class="special">:</span>
  <span class="identifier">tcp_connection</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_service</span><span class="special">&amp;</span> <span class="identifier">io_service</span><span class="special">)</span>
    <span class="special">:</span> <span class="identifier">socket_</span><span class="special">(</span><span class="identifier">io_service</span><span class="special">)</span>
  <span class="special">{</span>
  <span class="special">}</span>

  <span class="keyword">void</span> <span class="identifier">handle_write</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">&amp;</span> <span class="comment">/*error*/</span><span class="special">,</span>
      <span class="identifier">size_t</span> <span class="comment">/*bytes_transferred*/</span><span class="special">)</span>
  <span class="special">{</span>
  <span class="special">}</span>

  <span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span> <span class="identifier">socket_</span><span class="special">;</span>
  <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">message_</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<h5>
<a name="boost_asio.tutorial.tutdaytime3.h3"></a>
        <span class="phrase"><a name="boost_asio.tutorial.tutdaytime3.removing_unused_handler_parameters"></a></span><a class="link" href="tutdaytime3.html#boost_asio.tutorial.tutdaytime3.removing_unused_handler_parameters">Removing
        unused handler parameters</a>
      </h5>
<p>
        You may have noticed that the <code class="computeroutput"><span class="identifier">error</span></code>,
        and <code class="computeroutput"><span class="identifier">bytes_transferred</span></code> parameters
        are not used in the body of the <code class="computeroutput"><span class="identifier">handle_write</span><span class="special">()</span></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">  <span class="keyword">void</span> <span class="identifier">handle_write</span><span class="special">()</span>
  <span class="special">{</span>
  <span class="special">}</span>
</pre>
<p>
        The boost::asio::async_write() call used to initiate the call can then be
        changed to just:
      </p>
<pre class="programlisting">  <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">socket_</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">message_</span><span class="special">),</span>
      <span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">tcp_connection</span><span class="special">::</span><span class="identifier">handle_write</span><span class="special">,</span> <span class="identifier">shared_from_this</span><span class="special">()));</span>
</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 &#169; 2003-2014 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="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tutdaytime3/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>