summaryrefslogtreecommitdiff
path: root/docs/tutorials/006/page05.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tutorials/006/page05.html')
-rw-r--r--docs/tutorials/006/page05.html503
1 files changed, 0 insertions, 503 deletions
diff --git a/docs/tutorials/006/page05.html b/docs/tutorials/006/page05.html
deleted file mode 100644
index 2b79e79c7b9..00000000000
--- a/docs/tutorials/006/page05.html
+++ /dev/null
@@ -1,503 +0,0 @@
-<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 006</TITLE>
-</HEAD>
-<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
-
-<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER>
-
-<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER>
-
-
-<P>
-<HR WIDTH="100%">
-
-<P><A HREF="client_handler.cpp">client_handler.cpp</A>
-exposes all the things I've been hinting at.&nbsp; Pay special attention
-to the decision made in open() as well as the bit of cleverness in svc().
-
-<P>
-<HR WIDTH="100%">
-
-<P><FONT FACE="Arial,Helvetica">// $Id: client_handler.cpp,v 1.1 1998/08/30
-23:47:13 schmidt Exp $</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; In client_handler.h I alluded
-to the fact that we'll mess around with a</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Client_Acceptor pointer.&nbsp;
-To do so, we need the Client_Acceptor object</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; declaration.</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; We know that including client_handler.h
-is redundant because</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; client_acceptor.h includes
-it.&nbsp; Still, the sentry prevents double-inclusion</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; from causing problems and
-it's sometimes good to be explicit about what</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; we're using.</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; On the other hand, we don't
-directly include any ACE header files here.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">#include "client_acceptor.h"</FONT>
-<BR><FONT FACE="Arial,Helvetica">#include "client_handler.h"</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Our constructor doesn't do
-anything.&nbsp; That's generally a good idea.&nbsp; Unless</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; you want to start throwing
-exceptions, there isn't a really good way to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; indicate that a constructor
-has failed.&nbsp; If I had my way, I'd have a boolean</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; return code from it that
-would cause new to return 0 if I failed.&nbsp; Oh</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; well...</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">Client_Handler::Client_Handler (void)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Our destructor doesn't do
-anything either.&nbsp; That is also by design.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Remember, we really want
-folks to use destroy() to get rid of us.&nbsp; If that's</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; so, then there's nothing
-left to do when the destructor gets invoked.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">Client_Handler::~Client_Handler (void)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; The much talked about destroy()
-method!&nbsp; The reason I keep going on about</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; this is because it's just
-a Bad Idea (TM) to do real work inside of a</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; destructor.&nbsp;&nbsp; Although
-this method is void, it really should return</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; int so that it can tell the
-caller there was a problem.&nbsp; Even as</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; void you could at least throw
-an exception which you would never want</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; to do in a destructor.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">void Client_Handler::destroy (void)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; We probably got
-here because of an error on the stream, so the peer</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; connection is
-probably already closed.&nbsp; Still... there are other ways to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; get here and
-closing a closed peer doesn't hurt.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; this->peer ().close ();</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Tell the reactor
-to forget all about us.&nbsp; Notice that we use the same args</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; here that we
-use in the open() method to register ourselves.&nbsp; In addition,</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; we use the DONT_CALL
-flag to prevent handle_close() being called.&nbsp; Since we</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; likely got here
-due to handle_close(), that could cause a bit of nasty</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; recursion!</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; this->reactor ()->remove_handler
-(this,</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL);</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; This is how we're
-able to tell folks not to use delete.&nbsp; By</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; deleting our
-own instance, we take care of memory leaks after ensuring</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; that the object
-is shut down correctly.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; delete this;</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; As mentioned before, the
-open() method is called by the Client_Acceptor when</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; a new client connection has
-been accepted.&nbsp; The Client_Acceptor instance</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; pointer is cast to a void*
-and given to us here.&nbsp; We'll use that to avoid</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; some global data...</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">int Client_Handler::open (void *_acceptor)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; We need this
-to store the address of the client that we are now connected</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; to.&nbsp; We'll
-use it later to display a debug message.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_INET_Addr addr;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Our ACE_Svc_Handler
-baseclass gives us the peer() method as a way to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; access our underlying
-ACE_SOCK_Stream.&nbsp; On that object, we can invoke the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; get_remote_addr()
-method to get get an ACE_INET_Addr having our client's</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; address information.
-As with most ACE methods, we'll get back (and return)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; a -1 if there
-was any kind of error.&nbsp; Once we have the ACE_INET_Addr, we</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; can query it
-to find out the clien's host name, TCP/IP address, TCP/IP</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; port value and
-so forth.&nbsp; One word of warning:&nbsp;&nbsp; the get_host_name()</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; method of ACE_INET_Addr
-may return you an empty string if your name server</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; can't resolve
-it.&nbsp; On the other hand, get_host_addr() will always give you</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; the dotted-decimal
-string representing the TCP/IP address.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; if (this->peer ().get_remote_addr
-(addr) == -1)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; {</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return
--1;</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; }</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Convert the void*
-to a Client_Acceptor*.&nbsp; You should probably use those</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; fancy new C++
-cast operators but I can never remember how/when to do so.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Since you can
-cast just about anything around a void* without compiler</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; warnings be very
-sure of what you're doing when you do this kind of thing.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; That's where
-the new-style cast operators can save you.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; Client_Acceptor *acceptor = (Client_Acceptor
-*) _acceptor;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Our Client_Acceptor
-is constructed with a concurrency strategy.&nbsp; Here, we</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; go back to it
-to find out what that strategy was.&nbsp; If thread-per-connection</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; was selected
-then we simply activate a thread for ourselves and exit.&nbsp; Our</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; svc() method
-will then begin executing in that thread.</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; If we are told
-to use the single-threaded strategy, there is no difference</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; between this
-and the Tutorial 5 implementation.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; if( acceptor->thread_per_connection()
-)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; {</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; return this->activate();</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; }</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Our reactor reference
-will be set when we register ourselves but I decided</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; to go ahead and
-set it here.&nbsp; No good reason really...</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; this->reactor (acceptor->reactor
-());</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; If we managed
-to get the client's address then we're connected to a real</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; and valid client.&nbsp;
-I suppose that in some cases, the client may connect</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; and disconnect
-so quickly that it is invalid by the time we get here. In</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; any case, the
-test above should always be done to ensure that the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; connection is
-worth keeping.</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Now, regiser ourselves
-with a reactor and tell that reactor that we want</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; to be notified
-when there is something to read.&nbsp; Remember, we took our</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; reactor value
-from the acceptor which created us in the first place.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Since we're exploring
-a single-threaded implementation, this is the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; correct thing
-to do.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; if (this->reactor ()->register_handler
-(this, ACE_Event_Handler::READ_MASK) == -1)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; {</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE_ERROR_RETURN
-((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1);</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; }</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Here, we use
-the ACE_INET_Addr object to print a message with the name of</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; the client we're
-connected to.&nbsp; Again, it is possible that you'll get an</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; empty string
-for the host name if your DNS isn't configured correctly or</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; if there is some
-other reason that a TCP/IP addreess cannot be converted</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; into a host name.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_DEBUG ((LM_DEBUG, "(%P|%t)
-connected with %s\n", addr.get_host_name ()));</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Always return
-zero on success.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; return 0;</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; As mentioned in the header,
-the typical way to close an object in a threaded</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; context is to invoke it's
-close() method.&nbsp; Since we already have a handle_close()</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; method built to cleanup after
-us, we'll just forward the request on to that</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; object.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">int Client_Handler::close(u_long flags)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-this->handle_close(ACE_INVALID_HANDLE,0);</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-After we've taken care of ourselves, call the baseclass method</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-to do any other necessary cleanup.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-return inherited::close();</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; In the open() method, we
-registered with the reactor and requested to be</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; notified when there is data
-to be read.&nbsp; When the reactor sees that activity</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; it will invoke this handle_input()
-method on us.&nbsp; As I mentioned, the _handle</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; parameter isn't useful to
-us but it narrows the list of methods the reactor</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; has to worry about and the
-list of possible virtual functions we would have</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; to override.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">int Client_Handler::handle_input (ACE_HANDLE
-_handle)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Some compilers
-don't like it when you fail to use a parameter.&nbsp; This macro</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; will keep 'em
-quiet for you.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_UNUSED_ARG (_handle);</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Now, we create
-and initialize a buffer for receiving the data.&nbsp; Since this</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; is just a simple
-test app, we'll use a small buffer size.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; char buf[128];</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; memset (buf, 0, sizeof (buf));</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Invoke the process()
-method with a pointer to our data area.&nbsp; We'll let</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; that method worry
-about interfacing with the data.&nbsp; You might choose to go</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; ahead and read
-the data and then pass the result to process().&nbsp; However,</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; application logic
-may require that you read a few bytes to determine what</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; else to read...&nbsp;
-It's best if we push that all into the application-logic</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; level.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; return this->process (buf, sizeof
-(buf));</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; If we return -1 out of handle_input()
-or if the reactor sees other problems</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; with us then handle_close()
-will be called.&nbsp; It uses our destroy() method to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; shut us down cleanly and
-get rid of our instance.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">int Client_Handler::handle_close (ACE_HANDLE
-_handle, ACE_Reactor_Mask _mask)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_UNUSED_ARG (_handle);</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_UNUSED_ARG (_mask);</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; this->destroy ();</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; return 0;</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; The ACE_Svc_Handler&lt;>
-is ultimately derived from ACE_Task&lt;>.&nbsp; If you want to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; create a multi-threaded application,
-these are your tools!&nbsp; Simply override</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; the svc() method in your
-derivative and arrange for your activate() method</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; to be called.&nbsp; The svc()
-method then executes in the new thread.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">int Client_Handler::svc(void)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Like handle_input(),
-we create a buffer for loading the data.&nbsp; Doing so</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; in handle_input()
-doesn't help any but there is a small performance increase</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; by doing this
-here:&nbsp; the buffer is created once when the thread is created</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; instead of for
-each invocation of process().</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; char buf[128];</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; // Forever...</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; while( 1 )</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; {</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; // Clean the
-buffer...</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; memset (buf,
-0, sizeof (buf));</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Invoke the proces() method to read and process the data.&nbsp; This is</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-exactly the way it is used by handle_input().&nbsp; That's the reason I</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-created process() in the first place:&nbsp; so that it can be used in either</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-concurrency strategy.&nbsp; Since process() has all of our application-level</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-logic, it's nice that it doesn't have to change when we decide to go</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-multi-threaded.</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Notice that since the recv() method call in process() blocks until</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-there is data ready, this thread doesn't consume any CPU time until</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-there is actually data sent from the client.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; if( this->process(buf,sizeof(buf))
-== -1 )</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; {</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return(-1);</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; }</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; }</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; return(0);</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; And, at last, we get to the
-application-logic level.&nbsp; Out of everything</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; we've done so far, this is
-the only thing that really has anything to do</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; with what your application
-will do.&nbsp; In this method we will read and process</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; the client's data.&nbsp;
-In a real appliation, you will probably have a bit more</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; in main() to deal with command
-line options but after that point, all of the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; action takes place here.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">int Client_Handler::process (char *_rdbuf,
-int _rdbuf_len)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Using the buffer
-provided for us, we read the data from the client. If</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; there is a read
-error (eg -- recv() returns -1) then it's a pretty good</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; bet that the
-connection is gone.&nbsp; Likewise, if we read zero bytes then</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; something wrong
-has happened.&nbsp; The reactor wouldn't have called us if</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; there wasn't
-some kind of read activity but there wouldn't be activity if</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; there were no
-bytes to read...</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; On the other hand,
-if we got some data then we can display it in a&nbsp; debug</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; message for everyone
-to see.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; switch (this->peer ().recv (_rdbuf,
-_rdbuf_len))</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; {</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; case -1:</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE_ERROR_RETURN
-((LM_ERROR, "(%P|%t) %p bad read\n", "client"), -1);</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; case 0:</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE_ERROR_RETURN
-((LM_ERROR, "(%P|%t) closing daemon (fd = %d)\n", this->get_handle ()),
--1);</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; default:</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE_DEBUG
-((LM_DEBUG, "(%P|%t) from client: %s", _rdbuf));</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; }</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; return 0;</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT>
-
-<P>
-<HR WIDTH="100%">
-
-<P>Well, that's it!&nbsp; After all the talk &amp; the hype, you would
-have expected it to be more difficult to create a multi-threaded server.&nbsp;
-Surprise!&nbsp; It really is that easy.&nbsp; You still have to handle
-contention issues which we haven't addressed here and that is a rather
-nasty topic.&nbsp; Still, for the simple case, this is all you have to
-do.
-
-<P>The next page is the last for this tutorial.&nbsp; Head on over there
-&amp; we'll round up the file list one last time.
-
-<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="..">Tutorial
-Index</A>] [<A HREF="page06.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>