summaryrefslogtreecommitdiff
path: root/docs/tutorials/005/page05.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tutorials/005/page05.html')
-rw-r--r--docs/tutorials/005/page05.html153
1 files changed, 72 insertions, 81 deletions
diff --git a/docs/tutorials/005/page05.html b/docs/tutorials/005/page05.html
index d9126ecbc81..029683a7ca1 100644
--- a/docs/tutorials/005/page05.html
+++ b/docs/tutorials/005/page05.html
@@ -22,9 +22,11 @@ rest of the application all together.
<P>
<HR WIDTH="100%">
-<pre>
-<FONT FACE="Arial,Helvetica">
-/*
+<PRE>
+
+<font color=red>// $Id$</font>
+
+<font color=red>/*
In client_handler.h I alluded to the fact that we'll mess around with a
Client_Acceptor pointer. To do so, we need the Client_Acceptor object
declaration.
@@ -35,109 +37,109 @@ rest of the application all together.
we're using.
On the other hand, we don't directly include any ACE header files here.
- */
-#include "client_acceptor.h"
-#include "client_handler.h"
+ */</font>
+<font color=blue>#include</font> "<font color=green>client_acceptor.h</font>"
+<font color=blue>#include</font> "<font color=green>client_handler.h</font>"
-/*
+<font color=red>/*
Our constructor doesn't do anything. That's generally a good idea. Unless
you want to start throwing exceptions, there isn't a really good way to
indicate that a constructor has failed. If I had my way, I'd have a boolean
return code from it that would cause new to return 0 if I failed. Oh
well...
- */
-Client_Handler::Client_Handler (void)
+ */</font>
+<font color=#008888>Client_Handler::Client_Handler</font> (void)
{
}
-/*
+<font color=red>/*
Our destructor doesn't do anything either. That is also by design.
Remember, we really want folks to use destroy() to get rid of us. If that's
so, then there's nothing left to do when the destructor gets invoked.
- */
-Client_Handler::~Client_Handler (void)
+ */</font>
+<font color=#008888>Client_Handler::~Client_Handler</font> (void)
{
- // Make sure that our peer closes when we're deleted. This
- // will probably happend when the peer is deleted but it
- // doesn't hurt to be explicit.
+ <font color=red>// Make sure that our peer closes when we're deleted. This</font>
+ <font color=red>// will probably happend when the peer is deleted but it</font>
+ <font color=red>// doesn't hurt to be explicit.</font>
this->peer ().close ();
}
-/*
+<font color=red>/*
The much talked about destroy() method! The reason I keep going on about
this is because it's just a Bad Idea (TM) to do real work inside of a
destructor. Although this method is void, it really should return
int so that it can tell the caller there was a problem. Even as
void you could at least throw an exception which you would never want
to do in a destructor.
- */
-void Client_Handler::destroy (void)
+ */</font>
+void <font color=#008888>Client_Handler::destroy</font> (void)
{
- /*
+ <font color=red>/*
Tell the reactor to forget all about us. Notice that we use the same args
here that we use in the open() method to register ourselves. In addition,
we use the DONT_CALL flag to prevent handle_close() being called. Since we
likely got here due to handle_close(), that could cause a bit of nasty
recursion!
- */
+ */</font>
this->reactor ()->remove_handler (this,
- ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL);
+ ACE_Event_Handler:: READ_MASK | <font color=#008888>ACE_Event_Handler::DONT_CALL</font>);
- /*
+ <font color=red>/*
This is how we're able to tell folks not to use delete. By
deleting our own instance, we take care of memory leaks after ensuring
that the object is shut down correctly.
- */
+ */</font>
delete this;
}
-/*
+<font color=red>/*
As mentioned before, the open() method is called by the Client_Acceptor when
a new client connection has been accepted. The Client_Acceptor instance
pointer is cast to a void* and given to us here. We'll use that to avoid
some global data...
- */
-int Client_Handler::open (void *_acceptor)
+ */</font>
+int <font color=#008888>Client_Handler::open</font> (void *_acceptor)
{
- /*
+ <font color=red>/*
Convert the void* to a Client_Acceptor*. You should probably use those
fancy new C++ cast operators but I can never remember how/when to do so.
Since you can cast just about anything around a void* without compiler
warnings be very sure of what you're doing when you do this kind of thing.
That's where the new-style cast operators can save you.
- */
+ */</font>
Client_Acceptor *acceptor = (Client_Acceptor *) _acceptor;
- /*
+ <font color=red>/*
Our reactor reference will be set when we register ourselves but I decided
to go ahead and set it here. No good reason really...
- */
+ */</font>
this->reactor (acceptor->reactor ());
- /*
+ <font color=red>/*
We need this to store the address of the client that we are now connected
to. We'll use it later to display a debug message.
- */
+ */</font>
ACE_INET_Addr addr;
- /*
+ <font color=red>/*
Our ACE_Svc_Handler baseclass gives us the peer() method as a way to
access our underlying ACE_SOCK_Stream. On that object, we can invoke the
- get_remote_addr() method to get an ACE_INET_Addr having our client's
+ get_remote_addr() method to get get an ACE_INET_Addr having our client's
address information. As with most ACE methods, we'll get back (and return)
a -1 if there was any kind of error. Once we have the ACE_INET_Addr, we
- can query it to find out the client's host name, TCP/IP address, TCP/IP
+ can query it to find out the clien's host name, TCP/IP address, TCP/IP
port value and so forth. One word of warning: the get_host_name()
- method of ACE_INET_Addr may return an empty string if your name server
+ method of ACE_INET_Addr may return you an empty string if your name server
can't resolve it. On the other hand, get_host_addr() will always give you
the dotted-decimal string representing the TCP/IP address.
- */
+ */</font>
if (this->peer ().get_remote_addr (addr) == -1)
{
return -1;
}
- /*
+ <font color=red>/*
If we managed to get the client's address then we're connected to a real
and valid client. I suppose that in some cases, the client may connect
and disconnect so quickly that it is invalid by the time we get here. In
@@ -149,68 +151,68 @@ int Client_Handler::open (void *_acceptor)
reactor value from the acceptor which created us in the first place.
Since we're exploring a single-threaded implementation, this is the
correct thing to do.
- */
- if (this->reactor ()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1)
+ */</font>
+ if (this->reactor ()->register_handler (this, <font color=#008888>ACE_Event_Handler::READ_MASK</font>) == -1)
{
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) can't register with reactor\n</font>"), -1);
}
- /*
+ <font color=red>/*
Here, we use the ACE_INET_Addr object to print a message with the name of
the client we're connected to. Again, it is possible that you'll get an
empty string for the host name if your DNS isn't configured correctly or
if there is some other reason that a TCP/IP addreess cannot be converted
into a host name.
- */
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", addr.get_host_name ()));
+ */</font>
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) connected with %s\n</font>", addr.get_host_name ()));
- /*
+ <font color=red>/*
Always return zero on success.
- */
+ */</font>
return 0;
}
-/*
+<font color=red>/*
In the open() method, we registered with the reactor and requested to be
notified when there is data to be read. When the reactor sees that activity
it will invoke this handle_input() method on us. As I mentioned, the _handle
parameter isn't useful to us but it narrows the list of methods the reactor
has to worry about and the list of possible virtual functions we would have
to override.
- */
-int Client_Handler::handle_input (ACE_HANDLE _handle)
+ */</font>
+int <font color=#008888>Client_Handler::handle_input</font> (ACE_HANDLE _handle)
{
- /*
+ <font color=red>/*
Some compilers don't like it when you fail to use a parameter. This macro
will keep 'em quiet for you.
- */
+ */</font>
ACE_UNUSED_ARG (_handle);
- /*
+ <font color=red>/*
Now, we create and initialize a buffer for receiving the data. Since this
is just a simple test app, we'll use a small buffer size.
- */
+ */</font>
char buf[128];
- ACE_OS::memset (buf, 0, sizeof (buf));
+ <font color=#008888>ACE_OS::memset</font> (buf, 0, sizeof (buf));
- /*
+ <font color=red>/*
Invoke the process() method with a pointer to our data area. We'll let
that method worry about interfacing with the data. You might choose to go
ahead and read the data and then pass the result to process(). However,
application logic may require that you read a few bytes to determine what
else to read... It's best if we push that all into the application-logic
level.
- */
+ */</font>
return this->process (buf, sizeof (buf));
}
-/*
+<font color=red>/*
If we return -1 out of handle_input() or if the reactor sees other problems
with us then handle_close() will be called. The reactor framework
will take care of removing us (due to the -1), so we don't need to
use the destroy() method. Instead, we just delete ourselves directly.
- */
-int Client_Handler::handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask)
+ */</font>
+int <font color=#008888>Client_Handler::handle_close</font> (ACE_HANDLE _handle, ACE_Reactor_Mask _mask)
{
ACE_UNUSED_ARG (_handle);
ACE_UNUSED_ARG (_mask);
@@ -219,17 +221,17 @@ int Client_Handler::handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask)
return 0;
}
-/*
+<font color=red>/*
And, at last, we get to the application-logic level. Out of everything
we've done so far, this is the only thing that really has anything to do
with what your application will do. In this method we will read and process
the client's data. In a real appliation, you will probably have a bit more
in main() to deal with command line options but after that point, all of the
action takes place here.
- */
-int Client_Handler::process (char *_rdbuf, int _rdbuf_len)
+ */</font>
+int <font color=#008888>Client_Handler::process</font> (char *_rdbuf, int _rdbuf_len)
{
- /*
+ <font color=red>/*
Using the buffer provided for us, we read the data from the client. If
there is a read error (eg -- recv() returns -1) then it's a pretty good
bet that the connection is gone. Likewise, if we read zero bytes then
@@ -239,30 +241,19 @@ int Client_Handler::process (char *_rdbuf, int _rdbuf_len)
On the other hand, if we got some data then we can display it in a debug
message for everyone to see.
- */
+ */</font>
switch (this->peer ().recv (_rdbuf, _rdbuf_len))
{
case -1:
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) %p bad read\n</font>", "<font color=green>client</font>"), -1);
case 0:
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing daemon (fd = %d)\n", this->get_handle ()), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) closing daemon (fd = %d)\n</font>", this->get_handle ()), -1);
default:
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) from client: %s", _rdbuf));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) from client: %s</font>", _rdbuf));
}
return 0;
}
-</pre>
-<HR WIDTH="100%">
-
-<P>That's the last of the C++&nbsp;code.&nbsp; On the final two pages I'll
-go over the Makefile and a short perl script I wrote to "assist"&nbsp;the
-Makefile.&nbsp; Please... Continue...
-
-<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="..">Tutorial
-Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+</PRE>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER>