diff options
Diffstat (limited to 'docs/tutorials/007/page02.html')
-rw-r--r-- | docs/tutorials/007/page02.html | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/docs/tutorials/007/page02.html b/docs/tutorials/007/page02.html new file mode 100644 index 00000000000..c6e7bedec43 --- /dev/null +++ b/docs/tutorials/007/page02.html @@ -0,0 +1,197 @@ +<HTML> +<HEAD> + <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> + <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> + <META NAME="Author" CONTENT="James CE Johnson"> + <META NAME="Description" CONTENT="A first step towards using ACE productively"> + <TITLE>ACE Tutorial 007</TITLE> +</HEAD> +<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> + +<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> + +<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> + + +<P> +<HR WIDTH="100%"> + +<P>As usualy, we start with <A HREF="server.cpp">server.cpp</A> +<BR> +<HR WIDTH="100%"> + +<P><FONT FACE="Arial,Helvetica">// $Id: server.cpp,v 1.1 1998/08/30 16:04:12 +jcej Exp $</FONT> + +<P><FONT FACE="Arial,Helvetica">/*</FONT> +<BR><FONT FACE="Arial,Helvetica"> We try to keep main() very +simple. One of the ways we do that is to push</FONT> +<BR><FONT FACE="Arial,Helvetica"> much of the complicated stuff +into worker objects. In this case, we only</FONT> +<BR><FONT FACE="Arial,Helvetica"> need to include the acceptor +header in our main source file. We let it</FONT> +<BR><FONT FACE="Arial,Helvetica"> worry about the "real work".</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> + +<P><FONT FACE="Arial,Helvetica">#include "client_acceptor.h"</FONT> + +<P><FONT FACE="Arial,Helvetica">/*</FONT> +<BR><FONT FACE="Arial,Helvetica"> As before, we create a simple +signal handler that will set our finished</FONT> +<BR><FONT FACE="Arial,Helvetica"> flag. There are, of +course, more elegant ways to handle program shutdown</FONT> +<BR><FONT FACE="Arial,Helvetica"> requests but that isn't really +our focus right now, so we'll just do the</FONT> +<BR><FONT FACE="Arial,Helvetica"> easiest thing.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> + +<P><FONT FACE="Arial,Helvetica">static sig_atomic_t finished = 0;</FONT> +<BR><FONT FACE="Arial,Helvetica">extern "C" void handler (int)</FONT> +<BR><FONT FACE="Arial,Helvetica">{</FONT> +<BR><FONT FACE="Arial,Helvetica"> finished = 1;</FONT> +<BR><FONT FACE="Arial,Helvetica">}</FONT> + +<P><FONT FACE="Arial,Helvetica">/*</FONT> +<BR><FONT FACE="Arial,Helvetica"> A server has to listen for +clients at a known TCP/IP port. The default ACE</FONT> +<BR><FONT FACE="Arial,Helvetica"> port is 10002 (at least on +my system) and that's good enough for what we</FONT> +<BR><FONT FACE="Arial,Helvetica"> want to do here. Obviously, +a more robust application would take a command</FONT> +<BR><FONT FACE="Arial,Helvetica"> line parameter or read from +a configuration file or do some other clever</FONT> +<BR><FONT FACE="Arial,Helvetica"> thing. Just like the +signal handler above, though, that's what we want to</FONT> +<BR><FONT FACE="Arial,Helvetica"> focus on, so we're taking +the easy way out.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> + +<P><FONT FACE="Arial,Helvetica">static const u_short PORT = ACE_DEFAULT_SERVER_PORT;</FONT> + +<P><FONT FACE="Arial,Helvetica">/*</FONT> +<BR><FONT FACE="Arial,Helvetica"> Finally, we get to main. +Some C++ compilers will complain loudly if your</FONT> +<BR><FONT FACE="Arial,Helvetica"> function signature doesn't +match the prototype. Even though we're not</FONT> +<BR><FONT FACE="Arial,Helvetica"> going to use the parameters, +we still have to specify them.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> + +<P><FONT FACE="Arial,Helvetica">int main (int argc, char *argv[])</FONT> +<BR><FONT FACE="Arial,Helvetica">{</FONT> +<BR><FONT FACE="Arial,Helvetica">/*</FONT> +<BR><FONT FACE="Arial,Helvetica"> In our earlier servers, we +used a global pointer to get to the reactor. I've</FONT> +<BR><FONT FACE="Arial,Helvetica"> never really liked that idea, +so I've moved it into main() this time. When</FONT> +<BR><FONT FACE="Arial,Helvetica"> we get to the Client_Handler +object you'll see how we manage to get a</FONT> +<BR><FONT FACE="Arial,Helvetica"> pointer back to this reactor.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> +<BR><FONT FACE="Arial,Helvetica"> ACE_Reactor reactor;</FONT> + +<P><FONT FACE="Arial,Helvetica"> /*</FONT> +<BR><FONT FACE="Arial,Helvetica"> The acceptor +will take care of letting clients connect to us. It will</FONT> +<BR><FONT FACE="Arial,Helvetica"> also arrange +for a Client_Handler to be created for each new client.</FONT> +<BR><FONT FACE="Arial,Helvetica"> Since we're only +going to listen at one TCP/IP port, we only need one</FONT> +<BR><FONT FACE="Arial,Helvetica"> acceptor. +If we wanted, though, we could create several of these and</FONT> +<BR><FONT FACE="Arial,Helvetica"> listen at several +ports. (That's what we would do if we wanted to rewrite</FONT> +<BR><FONT FACE="Arial,Helvetica"> inetd for +instance.)</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> +<BR><FONT FACE="Arial,Helvetica"> Client_Acceptor peer_acceptor;</FONT> + +<P><FONT FACE="Arial,Helvetica"> /*</FONT> +<BR><FONT FACE="Arial,Helvetica"> Create an ACE_INET_Addr +that represents our endpoint of a connection. We</FONT> +<BR><FONT FACE="Arial,Helvetica"> then open our +acceptor object with that Addr. Doing so tells the acceptor</FONT> +<BR><FONT FACE="Arial,Helvetica"> where to listen +for connections. Servers generally listen at "well known"</FONT> +<BR><FONT FACE="Arial,Helvetica"> addresses. +If not, there must be some mechanism by which the client is</FONT> +<BR><FONT FACE="Arial,Helvetica"> informed of the +server's address.</FONT> + +<P><FONT FACE="Arial,Helvetica"> Note how ACE_ERROR_RETURN +is used if we fail to open the acceptor. This</FONT> +<BR><FONT FACE="Arial,Helvetica"> technique is +used over and over again in our tutorials.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> +<BR><FONT FACE="Arial,Helvetica"> if (peer_acceptor.open (ACE_INET_Addr +(PORT), &reactor) == -1)</FONT> +<BR><FONT FACE="Arial,Helvetica"> ACE_ERROR_RETURN ((LM_ERROR, +"%p\n", "open"), -1);</FONT> + +<P><FONT FACE="Arial,Helvetica"> /*</FONT> +<BR><FONT FACE="Arial,Helvetica"> Install our signal +handler. You can actually register signal handlers</FONT> +<BR><FONT FACE="Arial,Helvetica"> with the reactor. +You might do that when the signal handler is</FONT> +<BR><FONT FACE="Arial,Helvetica"> responsible for +performing "real" work. Our simple flag-setter doesn't</FONT> +<BR><FONT FACE="Arial,Helvetica"> justify deriving +from ACE_Event_Handler and providing a callback function</FONT> +<BR><FONT FACE="Arial,Helvetica"> though.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> +<BR><FONT FACE="Arial,Helvetica"> ACE_Sig_Action sa ((ACE_SignalHandler) +handler, SIGINT);</FONT> + +<P><FONT FACE="Arial,Helvetica"> /*</FONT> +<BR><FONT FACE="Arial,Helvetica"> Like ACE_ERROR_RETURN, +the ACE_DEBUG macro gets used quite a bit. It's a</FONT> +<BR><FONT FACE="Arial,Helvetica"> handy way to +generate uniform debug output from your program.</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> +<BR><FONT FACE="Arial,Helvetica"> ACE_DEBUG ((LM_DEBUG, "(%P|%t) +starting up server daemon\n"));</FONT> + +<P><FONT FACE="Arial,Helvetica"> /*</FONT> +<BR><FONT FACE="Arial,Helvetica"> This will loop +"forever" invoking the handle_events() method of our</FONT> +<BR><FONT FACE="Arial,Helvetica"> reactor. handle_events() +watches for activity on any registered handlers</FONT> +<BR><FONT FACE="Arial,Helvetica"> and invokes their +appropriate callbacks when necessary. Callback-driven</FONT> +<BR><FONT FACE="Arial,Helvetica"> programming is +a big thing in ACE, you should get used to it. If the</FONT> +<BR><FONT FACE="Arial,Helvetica"> signal handler +catches something, the finished flag will be set and we'll</FONT> +<BR><FONT FACE="Arial,Helvetica"> exit. Conveniently +enough, handle_events() is also interrupted by signals</FONT> +<BR><FONT FACE="Arial,Helvetica"> and will exit +back to the while() loop. (If you want your event loop to</FONT> +<BR><FONT FACE="Arial,Helvetica"> not be interrupted +by signals, checkout the <i>restart</i> flag on the</FONT> +<BR><FONT FACE="Arial,Helvetica"> open() method +of ACE_Reactor if you're interested.)</FONT> +<BR><FONT FACE="Arial,Helvetica"> */</FONT> +<BR><FONT FACE="Arial,Helvetica"> while (!finished)</FONT> +<BR><FONT FACE="Arial,Helvetica"> +reactor.handle_events ();</FONT> + +<P><FONT FACE="Arial,Helvetica"> ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting +down server daemon\n"));</FONT> +<BR><FONT FACE="Arial,Helvetica"> </FONT> +<BR><FONT FACE="Arial,Helvetica"> return 0;</FONT> +<BR><FONT FACE="Arial,Helvetica">}</FONT> + +<P> +<HR WIDTH="100%"> + +<P>Hmmm... No change there. Maybe I should leave out comments +on the stuff I don't change. Let's take a lookt at client_acceptor.h. + +<P> +<HR WIDTH="100%"> +<CENTER>[<A HREF="..">Tutorial +Index</A>] [<A HREF="page03.html">Continue +This Tutorial</A>]</CENTER> + +</BODY> +</HTML> |