diff options
Diffstat (limited to 'docs/tutorials/007/page02.html')
-rw-r--r-- | docs/tutorials/007/page02.html | 301 |
1 files changed, 125 insertions, 176 deletions
diff --git a/docs/tutorials/007/page02.html b/docs/tutorials/007/page02.html index c6e7bedec43..fabab39642d 100644 --- a/docs/tutorials/007/page02.html +++ b/docs/tutorials/007/page02.html @@ -11,187 +11,136 @@ <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%"> - +<HR> <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> +<PRE> +<font color=red>// $Id$</font> + +<font color=red>/* + We try to keep main() very simple. One of the ways we do that is to push + much of the complicated stuff into worker objects. In this case, we only + need to include the acceptor header in our main source file. We let it + worry about the "<font color=green>real work</font>". + */</font> + +<font color=blue>#include</font> "<font color=green>client_acceptor.h</font>" + +<font color=red>/* + As before, we create a simple signal handler that will set our finished + flag. There are, of course, more elegant ways to handle program shutdown + requests but that isn't really our focus right now, so we'll just do the + easiest thing. + */</font> + +static sig_atomic_t finished = 0; +extern "<font color=green>C</font>" void handler (int) +{ + finished = 1; +} + +<font color=red>/* + A server has to listen for clients at a known TCP/IP port. The default ACE + port is 10002 (at least on my system) and that's good enough for what we + want to do here. Obviously, a more robust application would take a command + line parameter or read from a configuration file or do some other clever + thing. Just like the signal handler above, though, that's what we want to + focus on, so we're taking the easy way out. + */</font> + +static const u_short PORT = ACE_DEFAULT_SERVER_PORT; + +<font color=red>/* + Finally, we get to main. Some C++ compilers will complain loudly if your + function signature doesn't match the prototype. Even though we're not + going to use the parameters, we still have to specify them. + */</font> + +int main (int argc, char *argv[]) +{ +<font color=red>/* + In our earlier servers, we used a global pointer to get to the reactor. I've + never really liked that idea, so I've moved it into main() this time. When + we get to the Client_Handler object you'll see how we manage to get a + pointer back to this reactor. + */</font> + ACE_Reactor reactor; + + <font color=red>/* + The acceptor will take care of letting clients connect to us. It will + also arrange for a Client_Handler to be created for each new client. + Since we're only going to listen at one TCP/IP port, we only need one + acceptor. If we wanted, though, we could create several of these and + listen at several ports. (That's what we would do if we wanted to rewrite + inetd for instance.) + */</font> + Client_Acceptor peer_acceptor; + + <font color=red>/* + Create an ACE_INET_Addr that represents our endpoint of a connection. We + then open our acceptor object with that Addr. Doing so tells the acceptor + where to listen for connections. Servers generally listen at "<font color=green>well known</font>" + addresses. If not, there must be some mechanism by which the client is + informed of the server's address. + + Note how ACE_ERROR_RETURN is used if we fail to open the acceptor. This + technique is used over and over again in our tutorials. + */</font> + if (peer_acceptor.open (ACE_INET_Addr (PORT), &reactor) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1); + + <font color=red>/* + Install our signal handler. You can actually register signal handlers + with the reactor. You might do that when the signal handler is + responsible for performing "<font color=green>real</font>" work. Our simple flag-setter doesn't + justify deriving from ACE_Event_Handler and providing a callback function + though. + */</font> + ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); + + <font color=red>/* + Like ACE_ERROR_RETURN, the ACE_DEBUG macro gets used quite a bit. It's a + handy way to generate uniform debug output from your program. + */</font> + ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) starting up server daemon\n</font>")); + + <font color=red>/* + This will loop "<font color=green>forever</font>" invoking the handle_events() method of our + reactor. handle_events() watches for activity on any registered handlers + and invokes their appropriate callbacks when necessary. Callback-driven + programming is a big thing in ACE, you should get used to it. If the + signal handler catches something, the finished flag will be set and we'll + exit. Conveniently enough, handle_events() is also interrupted by signals + and will exit back to the while() loop. (If you want your event loop to + not be interrupted by signals, checkout the <i>restart</i> flag on the + open() method of ACE_Reactor if you're interested.) + */</font> + while (!finished) + reactor.handle_events (); + + ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) shutting down server daemon\n</font>")); + + return 0; +} + +<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) +template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; +template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; +template class ACE_Guard<ACE_Mutex>; +template class ACE_Atomic_Op<ACE_Mutex, int>; +<font color=blue>#elif defined</font> (<font color=purple>ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA</font>) +<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> +<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> +<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard<ACE_Mutex> +<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Atomic_Op<ACE_Mutex, int> +<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> +</PRE> <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. +on the stuff I don't change. Let's take a look 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> +<P><HR WIDTH="100%"> +<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER> |