diff options
Diffstat (limited to 'docs/tutorials/015/page09.html')
-rw-r--r-- | docs/tutorials/015/page09.html | 227 |
1 files changed, 0 insertions, 227 deletions
diff --git a/docs/tutorials/015/page09.html b/docs/tutorials/015/page09.html deleted file mode 100644 index 9d1b818fbd3..00000000000 --- a/docs/tutorials/015/page09.html +++ /dev/null @@ -1,227 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Like any other event handler, the handle_input() method will be -responsible for getting data from the peer() and doing something with -it. In this case, we have a Protocol_Stream to deal with. We'll use -the stream for the actual I/O but we are ultimately responsible for -processing the data from the peer. To do that, we've created a -Handler_Task that fits within the Protocol_Stream framework to process -data that has been received. Handler::handle_input() will tell the stream that -it's time to read data and that data will eventually show up at -Handler_Task::recv() where we'll process it as required by our -application logic. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Handler.h</font>" -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* The Protocol_Stream gives us the option to insert a Protocol_Task - to process data received by the stream. We'll get into the details - more when we talk about the stream in detail. For now it's enough - to know that <font color=#008888>Handler_Task::recv</font>() will be invoked by the stream - after data from the client has been received and processed (eg -- - decrypted, uncompressed, and whatever else the protocol requires.) -*/</font> -class Handler_Task : public Protocol_Task -{ -public: - - <font color=red>// Typical...</font> - typedef Protocol_Task inherited; - - <font color=red>// Simple...</font> - Handler_Task(void); - ~Handler_Task(void); - -protected: - - <font color=red>// recv() is invoked after received data has been fully</font> - <font color=red>// processed by the protocol rules. Data processing typically</font> - <font color=red>// done in handle_input() can then be done here.</font> - int recv(ACE_Message_Block * message, - ACE_Time_Value *timeout = 0); -}; - -<font color=#008888>Handler::Handler</font>(void) -{ - ; -} - -<font color=#008888>Handler::~Handler</font>(void) -{ - ; -} - -<font color=red>/* The Acceptor will open() us once the peer() connection is - established. There are a couple of things we have to do here - before we're ready to receive data from the client. -*/</font> -int <font color=#008888>Handler::open</font> (void *) -{ - ACE_INET_Addr addr; - - <font color=red>// Make sure that we can get the peer's address. If we can't</font> - <font color=red>// then there may be a network error or something else that</font> - <font color=red>// will prevent communicating with the client. This is</font> - <font color=red>// something you'll want to do in every event handler you create.</font> - if (this->peer ().get_remote_addr (addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get remote addr\n</font>"), -1); - - <font color=red>// Announce the client</font> - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) connected with %s\n</font>", addr.get_host_name() )); - - <font color=red>// Here's the first new twist to the old event handler.</font> - <font color=red>// Before we can use the Protocol_Stream to communicate with</font> - <font color=red>// the peer, we must open() it. We provide the stream with</font> - <font color=red>// the peer() so that it will have a valid socket on which to</font> - <font color=red>// read client requests and send our responses. We also</font> - <font color=red>// provide a Handler_Task instance that will ultimately be</font> - <font color=red>// responsible for processing any client data we receive.</font> - int rval = stream().open( this->peer(), new Handler_Task() ); - - <font color=red>// Of course, we have to account for the chance that the</font> - <font color=red>// stream's open() may fail.</font> - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot open the protocol stream.\n</font>"), -1); - } - - <font color=red>// Now that we know the client is valid and that the stream is</font> - <font color=red>// ready for business we can register with the gloabl reactor</font> - <font color=red>// instance. Here again is an opportunity for improvement if</font> - <font color=red>// we expect to have mulitple Server object instances.</font> - if (<font color=#008888>ACE_Reactor::instance</font>()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot register with reactor\n</font>"), -1); - - return rval; -} - -<font color=red>/* This is a fairly typical destroy() method that can be shared by - both close() and handle_close(). -*/</font> -void <font color=#008888>Handler::destroy</font> (void) -{ - <font color=#008888>ACE_Reactor::instance</font>()->remove_handler(this,ACE_Event_Handler::READ_MASK|ACE_Event_Handler::DONT_CALL); - - this->peer ().close (); - - delete this; -} - -<font color=red>/* In this simple application we just forward the close() and - handle_close() requests right on to the destroy() method. -*/</font> - -int <font color=#008888>Handler::close</font> (u_long) -{ - this->destroy (); - return 0; -} - -int <font color=#008888>Handler::handle_close</font>(ACE_HANDLE, ACE_Reactor_Mask) -{ - this->destroy(); - return 0; -} - -<font color=red>/* Unlike a "<font color=green>traditional</font>" handle_input() ours is very simple. Because - of the use of the protocol stream, we delegate the read function to - the stream's get() and rely on our Handler_Task to do the real work. -*/</font> -int <font color=#008888>Handler::handle_input</font> (ACE_HANDLE) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Activity from client\n</font>" )); - - <font color=red>// This will cause a blocking read from the peer(). The data</font> - <font color=red>// will then be pushed through the protocol stream.</font> - if( stream().get( ) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get data from protocol stream\n</font>"), -1); - } - - return 0; -} - -<font color=red>/* A Protocol_Task is derived from ACE_Task and has the option of - running in one or more threads. I've chosen here to construct the - baseclass with no threads but it should work just fine with one or - more if you need. Unless you're sharing the Handler_Task with - several peers, however, you're probably just wasting a thread to - activate it. On the other hand, if your reactor is running in a - single thread (as in this example) then you can easily implement - thread-per-connection concurrency by giving the baseclass one thread. -*/</font> -<font color=#008888>Handler_Task::Handler_Task</font>(void) - : inherited() -{ - ; -} - -<font color=#008888>Handler_Task::~Handler_Task</font>(void) -{ - ; -} - -<font color=red>/* When installed into the protocol stream, the Handler_Task's recv() - method will be called when data is ready for processing. - */</font> -int <font color=#008888>Handler_Task::recv</font>(ACE_Message_Block * message, - ACE_Time_Value *timeout ) -{ - <font color=red>// Announce the request we got from the client</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Handler_Task::recv</font>() got (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a response message to send to the client</font> - ACE_Message_Block * response = new ACE_Message_Block( 128 ); - - <font color=red>// Nothing very original about this I'm afraid...</font> - <font color=#008888>ACE_OS::sprintf</font>( response->wr_ptr(), "<font color=green>You Said: (%s)</font>", message->rd_ptr() ); - response->wr_ptr( strlen(response->wr_ptr())+1 ); - - <font color=red>// Release the original message block now that we're through</font> - <font color=red>// "<font color=green>processing</font>" it.</font> - message->release(); - - <font color=red>// Turn the message around and send it back down the Stream.</font> - <font color=red>// In other words, we invoke the put() method on the</font> - <font color=red>// Protocol_Stream without having to have a direct reference</font> - <font color=red>// to the stream object.</font> - return this->reply( response, timeout ); -} -</PRE> -<HR> -<P> -That's it for the server-specific code. I think I've been fairly -successful in keeping it simple and to the point. There are a couple -of places where the as-yet-undescribed Protocol_Stream pops up and may -cause confusion. We're going to discuss that mystery now but before -we do here's the list of server files if you want to review: - -<UL> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -</UL> -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page10.html">Continue This Tutorial</A>]</CENTER> - |