diff options
Diffstat (limited to 'docs/tutorials/002/page03.html')
-rw-r--r-- | docs/tutorials/002/page03.html | 199 |
1 files changed, 152 insertions, 47 deletions
diff --git a/docs/tutorials/002/page03.html b/docs/tutorials/002/page03.html index 38ed438ed18..29bd85fa93e 100644 --- a/docs/tutorials/002/page03.html +++ b/docs/tutorials/002/page03.html @@ -1,65 +1,170 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> - <TITLE>ACE Tutorial 002</TITLE> - <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> + <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 002</TITLE> </HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> +<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> +<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER> -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 002<BR> -Creating a Better Server </FONT></B></P></CENTER> +<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER> -<P> -<HR WIDTH="100%"></P> -<P>This is what we do to create an acceptor from the ACE template:</P> +<P> +<HR WIDTH="100%"> -<UL> -<PRE> -1. #include "ace/Acceptor.h" -2. #include "ace/SOCK_Acceptor.h" - -3. typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor; -</PRE> -</UL> +<P>Now lets take a look at the new <A HREF="handler.h">Logging_Handler</A>: <P> -<HR></P> - -<P>Now, if you think that was difficult, you may as well give up now.</P> - -<OL> -<LI>The <I>Acceptor</I> header file defines the template we're about to -use. This is a totally generic object where all of the hard work as already -been done.</LI> - -<LI>Because we want to accept connections on an <I>ACE_SOCK_Stream</I>, -we have to pull in this header. It provides the API details that we will -need.</LI> - -<LI>Finally, create a <I>Logging_Acceptor</I> object based on the <I>ACE_Acceptor</I> -template. The first parameter <I>Logging_Handler</I> is an object we will -develop on the next page. This object will be created by the template-generated -code whenever a new connection request is accepted. The second parameter -tells the template what kind of acceptor to create. It is most important -that the first-parameter object and the second parameter be consistent -in the connetion types used.</LI> -</OL> - -<P>Obviously we're doing things a bit out of order here: <I>main</I> won't -be happy until it knows what a <I>Logging_Acceptor</I> is and the acceptor -won't be happy until it knows what a <I>Logging_Handler</I> is. The next -page pulls in this last definition for us and after that we tie it all -together.</P> +<HR WIDTH="100%"> +<BR> +<PRE>#ifndef LOGGING_HANDLER_H +#define LOGGING_HANDLER_H + +/* + Since we used the template to create the acceptor, we don't know if there is a + way to get to the reactor it uses. We'll take the easy way out and grab the + global pointer. (There is a way to get back to the acceptor's reactor that + we'll see later on.) + */ +extern ACE_Reactor * g_reactor; + +/* + This time we're deriving from ACE_Svc_Handler instead of ACE_Event_Handler. + The big reason for this is because it already knows how to contain a SOCK_Stream + and provides all of the method calls needed by the reactor. The second template + parameter is for some advanced stuff we'll do with later servers. For now, just + use it as is... + */ +class Logging_Handler : public ACE_Svc_Handler < ACE_SOCK_STREAM, ACE_NULL_SYNCH > +{ + +public: + + /* + The Acceptor<> template will open() us when there is a new client connection. + */ + int open (void *) + { + ACE_INET_Addr addr; + + /* + Ask the peer() (held in our baseclass) to tell us the address of the cient + which has connected. There may be valid reasons for this to fail where we + wouldn't want to drop the connection but I can't think of one. + */ + if (this->peer ().get_remote_addr (addr) == -1) + return -1; + + /* + The Acceptor<> won't register us with it's reactor, so we have to do so + ourselves. This is where we have to grab that global pointer. Notice + that we again use the READ_MASK so that handle_input() will be called + when the client does something. + */ + if (g_reactor->register_handler (this, ACE_Event_Handler::READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1); + + /* + Here's another new treat. We schedule a timer event. This particular one + will fire in two seconds and then every three seconds after that. It doesn't + serve any useful purpose in our application other than to show you how it + is done. + */ + else if (g_reactor->schedule_timer (this, 0, ACE_Time_Value (2), ACE_Time_Value (3)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "can'(%P|%t) t register with reactor\n"), -1); + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", addr.get_host_name() )); + + return 0; + } + + /* + This is a matter of style & maybe taste. Instead of putting all of this stuff + into a destructor, we put it here and request that everyone call destroy() + instead of 'delete'. + */ + void destroy (void) + { + /* + Cancel that timer we scheduled in open() + */ + g_reactor->cancel_timer (this); + + /* + Shut down the connection to the client. + */ + this->peer ().close (); + + /* + Free our memory. + */ + delete this; + } + + /* + If somebody doesn't like us, the will close() us. Actually, if our open() method + returns -1, the Acceptor<> will invoke close() on us for cleanup. + */ + int close (u_long) + { + /* + Clean up and go away. + */ + this->destroy (); + return 0; + } + +protected: + + /* + Respond to input just like Tutorial 1. + */ + int handle_input (ACE_HANDLE) + { + char buf[128]; + memset (buf, 0, sizeof (buf)); + + switch (this->peer ().recv (buf, sizeof buf)) + { + case -1: + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client logger"), -1); + case 0: + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing log daemon (fd = %d)\n", this->get_handle ()), -1); + default: + ACE_DEBUG ((LM_DEBUG, "(%P|%t) from client: %s", buf)); + } + + return 0; + } + + /* + When the timer expires, handle_timeout() will be called. The 'arg' is the value passed + after 'this' in the schedule_timer() call. You can pass in anything there that you can + cast to a void*. + */ + int handle_timeout (const ACE_Time_Value & tv, const void *arg) + { + ACE_DEBUG ((LM_DEBUG, "(%P|%t) handling timeout from this = %u\n", this)); + return 0; + } + +}; + +#endif // LOGGING_HANDLER_H</PRE> + <P> -<HR WIDTH="100%"></P> +<HR WIDTH="100%"> +<CENTER></CENTER> -<CENTER><P>[<A HREF="../../Tutorial">Tutorial Index</A>] [<A HREF="page02.html">Previous -Page</A>] [<A HREF="page04.html">Continue This Tutorial</A>] </P></CENTER> +<CENTER>[<A HREF="..">Tutorial +Index</A>] [<A HREF="page02.html">Previous +Page</A>] [<A HREF="page04.html">Continue +This Tutorial</A>]</CENTER> </BODY> </HTML> |