diff options
author | nobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-10-23 04:30:06 +0000 |
---|---|---|
committer | nobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-10-23 04:30:06 +0000 |
commit | 615c6979c0b339c7e2c89477899d63bf87e1dd93 (patch) | |
tree | 7e633c5be1c568b2e00f6ec8a2b6b3e6dbf3bd58 /docs/tutorials/005 | |
parent | 34cd7dceb74cbcc62c09c388504bec353bed4881 (diff) | |
download | ATCD-TAO-0_2_32.tar.gz |
This commit was manufactured by cvs2svn to create tag 'TAO-0_2_32'.TAO-0_2_32
Diffstat (limited to 'docs/tutorials/005')
-rw-r--r-- | docs/tutorials/005/00SetEnv | 2 | ||||
-rw-r--r-- | docs/tutorials/005/Makefile | 99 | ||||
-rw-r--r-- | docs/tutorials/005/acceptor | 6 | ||||
-rw-r--r-- | docs/tutorials/005/client_acceptor.h | 45 | ||||
-rw-r--r-- | docs/tutorials/005/client_handler.cpp | 233 | ||||
-rw-r--r-- | docs/tutorials/005/client_handler.h | 108 | ||||
-rw-r--r-- | docs/tutorials/005/fix.Makefile | 60 | ||||
-rw-r--r-- | docs/tutorials/005/handler | 81 | ||||
-rw-r--r-- | docs/tutorials/005/main | 36 | ||||
-rw-r--r-- | docs/tutorials/005/page01.html | 38 | ||||
-rw-r--r-- | docs/tutorials/005/page02.html | 201 | ||||
-rw-r--r-- | docs/tutorials/005/page03.html | 94 | ||||
-rw-r--r-- | docs/tutorials/005/page04.html | 192 | ||||
-rw-r--r-- | docs/tutorials/005/page05.html | 385 | ||||
-rw-r--r-- | docs/tutorials/005/page06.html | 195 | ||||
-rw-r--r-- | docs/tutorials/005/page07.html | 123 | ||||
-rw-r--r-- | docs/tutorials/005/page08.html | 53 | ||||
-rw-r--r-- | docs/tutorials/005/server.brk | 154 | ||||
-rw-r--r-- | docs/tutorials/005/server.cpp | 121 |
19 files changed, 0 insertions, 2226 deletions
diff --git a/docs/tutorials/005/00SetEnv b/docs/tutorials/005/00SetEnv deleted file mode 100644 index eca78e10c85..00000000000 --- a/docs/tutorials/005/00SetEnv +++ /dev/null @@ -1,2 +0,0 @@ -export ACE_ROOT=/local/src/ACE/ACE_wrappers -export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH diff --git a/docs/tutorials/005/Makefile b/docs/tutorials/005/Makefile deleted file mode 100644 index 6c4b01dbf9c..00000000000 --- a/docs/tutorials/005/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -# You can generally find a Makefile in the ACE examples, tests or the library -# itself that will satisfy our application needs. This one was taken from -# one of the examples. - - # Define the name of the binary we want to create. There has to be - # a CPP file $(BIN).cpp but it doesn't necessarily have to have your - # main() in it. Most of the time, though, it will. -BIN = server - - # Few applications will have a single source file. We use the FILES - # macro to build up a list of additional files to compile. Notice - # that we leave off the extension just as with BIN -FILES = -FILES += client_handler - - # The BUILD macro is used by the ACE makefiles. Basically, it tells - # the system what to build. I don't really know what VBIN is other - # than it is constructed from the value of BIN. Just go with it... -BUILD = $(VBIN) - - # Here we use some GNU make extensions to build the SRC macro. Basically, - # we're just adding .cpp to the value of BIN and for each entry of the - # FILES macro. -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - - # This is used by my Indent target below. It's not a part of standard - # ACE and you don't need it yourself. -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - - # This is where the real power lies! These included makefile components - # are similar to the C++ templates in ACE. That is, they do a tremendous - # amount of work for you and all you have to do is include them. - # As a matter of fact, in our project, I created a single file named - # "app.mk" that includes all of these. Our project makefiles then just - # need to include app.mk to get everything they need. - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - - # Sometimes I like to reformat my code to make it more readable. This is - # more useful for the comments than anything else. Unfortunately, the - # "indent" program doesn't quite grok C++ so I have to post-process it's - # output just a bit. -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - - # One of the targets in the ACE makefiles is "depend". It will invoke - # your compiler in a way that will generate a list of dependencies for - # you. This is a great thing! Unfortunately, it puts all of that mess - # directly into the Makefile. I prefer my Makefile to stay clean and - # uncluttered. The perl script referenced here pulls the dependency - # stuff back out of the Makefile and into a file ".depend" which we then - # include just like the makefile components above. -Depend : depend - perl fix.Makefile - -.depend : # - touch .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend diff --git a/docs/tutorials/005/acceptor b/docs/tutorials/005/acceptor deleted file mode 100644 index 45409e4ec3e..00000000000 --- a/docs/tutorials/005/acceptor +++ /dev/null @@ -1,6 +0,0 @@ - -1. #include "ace/Acceptor.h" -2. #include "ace/SOCK_Acceptor.h" - -3. typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor; - diff --git a/docs/tutorials/005/client_acceptor.h b/docs/tutorials/005/client_acceptor.h deleted file mode 100644 index fa3d3b41be8..00000000000 --- a/docs/tutorials/005/client_acceptor.h +++ /dev/null @@ -1,45 +0,0 @@ - -// $Id$ - -#ifndef CLIENT_ACCEPTOR_H -#define CLIENT_ACCEPTOR_H - -/* - The ACE_Acceptor<> template lives in the ace/Acceptor.h header file. You'll - find a very consitent naming convention between the ACE objects and the - headers where they can be found. In general, the ACE object ACE_Foobar will - - - be found in ace/Foobar.h. - */ - -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* - Since we want to work with sockets, we'll need a SOCK_Acceptor to allow the - clients to connect to us. - */ -#include "ace/SOCK_Acceptor.h" - -/* - The Client_Handler object we develop will be used to handle clients once - they're connected. The ACE_Acceptor<> template's first parameter requires - such an object. In some cases, you can get by with just a forward - declaration on the class, in others you have to have the whole thing. - */ -#include "client_handler.h" - -/* - Parameterize the ACE_Acceptor<> such that it will listen for socket - connection attempts and create Client_Handler objects when they happen. In - Tutorial 001, we wrote the basic acceptor logic on our own before we - realized that ACE_Acceptor<> was available. You'll get spoiled using the - ACE templates because they take away a lot of the tedious details! - */ -typedef ACE_Acceptor < Client_Handler, ACE_SOCK_ACCEPTOR > Client_Acceptor; - -#endif // CLIENT_ACCEPTOR_H diff --git a/docs/tutorials/005/client_handler.cpp b/docs/tutorials/005/client_handler.cpp deleted file mode 100644 index 42c1b29d66f..00000000000 --- a/docs/tutorials/005/client_handler.cpp +++ /dev/null @@ -1,233 +0,0 @@ - -// $Id$ - -/* - 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. - - We know that including client_handler.h is redundant because - client_acceptor.h includes it. Still, the sentry prevents double-inclusion - from causing problems and it's sometimes good to be explicit about what - 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" - -/* - 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) -{ -} - -/* - 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) -{ -} - -/* - 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) -{ - /* - We probably got here because of an error on the stream, so the peer - connection is probably already closed. Still... there are other ways to - get here and closing a closed peer doesn't hurt. - */ - this->peer ().close (); - - /* - 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! - */ - this->reactor ()->remove_handler (this, - ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL); - - /* - 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. - */ - delete this; -} - -/* - 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) -{ - /* - 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. - */ - Client_Acceptor *acceptor = (Client_Acceptor *) _acceptor; - - /* - Our reactor reference will be set when we register ourselves but I decided - to go ahead and set it here. No good reason really... - */ - this->reactor (acceptor->reactor ()); - - /* - 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. - */ - ACE_INET_Addr addr; - - /* - 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 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 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 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. - */ - if (this->peer ().get_remote_addr (addr) == -1) - { - return -1; - } - - /* - 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 - any case, the test above should always be done to ensure that the - connection is worth keeping. - - Now, regiser ourselves with a reactor and tell that reactor that we want - to be notified when there is something to read. Remember, we took our - 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) - { - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1); - } - - /* - 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 ())); - - /* - Always return zero on success. - */ - return 0; -} - -/* - 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) -{ - /* - Some compilers don't like it when you fail to use a parameter. This macro - will keep 'em quiet for you. - */ - ACE_UNUSED_ARG (_handle); - - /* - 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. - */ - char buf[128]; - ACE_OS::memset (buf, 0, sizeof (buf)); - - /* - 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. - */ - return this->process (buf, sizeof (buf)); -} - -/* - If we return -1 out of handle_input() or if the reactor sees other problems - with us then handle_close() will be called. It uses our destroy() method to - shut us down cleanly and get rid of our instance. - */ -int Client_Handler::handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask) -{ - ACE_UNUSED_ARG (_handle); - ACE_UNUSED_ARG (_mask); - - this->destroy (); - return 0; -} - -/* - 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) -{ - /* - 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 - something wrong has happened. The reactor wouldn't have called us if - there wasn't some kind of read activity but there wouldn't be activity if - there were no bytes to read... - - On the other hand, if we got some data then we can display it in a debug - message for everyone to see. - */ - switch (this->peer ().recv (_rdbuf, _rdbuf_len)) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client"), -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing daemon (fd = %d)\n", this->get_handle ()), -1); - default: - ACE_DEBUG ((LM_DEBUG, "(%P|%t) from client: %s", _rdbuf)); - } - - return 0; -} diff --git a/docs/tutorials/005/client_handler.h b/docs/tutorials/005/client_handler.h deleted file mode 100644 index b1e4af021d3..00000000000 --- a/docs/tutorials/005/client_handler.h +++ /dev/null @@ -1,108 +0,0 @@ - -// $Id$ - -#ifndef CLIENT_HANDLER_H -#define CLIENT_HANDLER_H - -/* - Our client handler must exist somewhere in the ACE_Event_Handler object - hierarchy. This is a requirement of the ACE_Reactor because it maintains - ACE_Event_Handler pointers for each registered event handler. You could - derive our Client_Handler directly from ACE_Event_Handler but you still have - to have an ACE_SOCK_Stream for the actually connection. With a direct - derivative of ACE_Event_Handler, you'll have to contain and maintain an - ACE_SOCK_Stream instance yourself. With ACE_Svc_Handler (which is a - derivative of ACE_Event_Handler) some of those details are handled for you. - - */ - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" - -/* - Another feature of ACE_Svc_Handler is it's ability to present the ACE_Task<> - interface as well. That's what the ACE_NULL_SYNCH parameter below is all - about. That's beyond our scope here but we'll come back to it in the next - tutorial when we start looking at concurrency options. - */ -class Client_Handler : public ACE_Svc_Handler < ACE_SOCK_STREAM, ACE_NULL_SYNCH > -{ -public: - - // Constructor... - Client_Handler (void); - - /* - The destroy() method is our preferred method of destruction. We could - have overloaded the delete operator but that is neither easy nor - intuitive (at least to me). Instead, we provide a new method of - destruction and we make our destructor protected so that only ourselves, - our derivatives and our friends can delete us. It's a nice - compromise. - */ - void destroy (void); - - /* - Most ACE objects have an open() method. That's how you make them ready - to do work. ACE_Event_Handler has a virtual open() method which allows us - to create this overrride. ACE_Acceptor<> will invoke this method after - creating a new Client_Handler when a client connects. Notice that the - parameter to open() is a void*. It just so happens that the pointer - points to the acceptor which created us. You would like for the parameter - to be an ACE_Acceptor<>* but since ACE_Event_Handler is generic, that - would tie it too closely to the ACE_Acceptor<> set of objects. In our - definition of open() you'll see how we get around that. - */ - int open (void *_acceptor); - - /* - When there is activity on a registered handler, the handle_input() method - of the handler will be invoked. If that method returns an error code (eg - -- -1) then the reactor will invoke handle_close() to allow the object to - clean itself up. Since an event handler can be registered for more than - one type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't have to - maintain state information between your handle_* method calls. The _handle - parameter is explained below... - */ - int handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask); - -protected: - - /* - When we register with the reactor, we're going to tell it that we want to - be notified of READ events. When the reactor sees that there is read - activity for us, our handle_input() will be invoked. The _handleg - provided is the handle (file descriptor in Unix) of the actual connection - causing the activity. Since we're derived from ACE_Svc_Handler<> and it - maintains it's own peer (ACE_SOCK_Stream) object, this is redundant for - us. However, if we had been derived directly from ACE_Event_Handler, we - may have chosen not to contain the peer. In that case, the _handleg - would be important to us for reading the client's data. - */ - int handle_input (ACE_HANDLE _handle); - - /* - This has nothing at all to do with ACE. I've added this here as a worker - function which I will call from handle_input(). That allows me to - introduce concurrencly in later tutorials with a no changes to the worker - function. You can think of process() as application-level code and - everything elase as application-framework code. - */ - int process (char *_rdbuf, int _rdbuf_len); - - /* - We don't really do anything in our destructor but we've declared it to be - protected to prevent casual deletion of this object. As I said above, I - really would prefer that everyone goes through the destroy() method to get - rid of us. - */ - ~Client_Handler (void); -}; - -#endif // CLIENT_HANDLER_H diff --git a/docs/tutorials/005/fix.Makefile b/docs/tutorials/005/fix.Makefile deleted file mode 100644 index e99c194114a..00000000000 --- a/docs/tutorials/005/fix.Makefile +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/perl - - # Open the Makefile that has been mangled by 'make depend' - # and suck it into a perl array. -open(IF,"<Makefile") || die; -@makefile = <IF>; -close(IF); - - # Now open our .depend file and a temporary Makefile. - # We'll split the original Makefile between these two. -open(DF,">.depend") || die; -open(MF,">Makefile.tmp") || die; - - # For each line we read out of the original file... -foreach (@makefile) { - - # If we're into the dependency section, write the line - # into the .depend file. - # - if( $depend ) { - print DF $_; - } - else { - # If we haven't gotten to the dependency section yet - # then see if the current line is the separator that - # "make depend" causes to be inserted. - # - if( m/^\Q# DO NOT DELETE THIS LINE -- g++dep uses it.\E/ ) { - - # If so, change our "mode" and skip this line. - ++$depend; - next; - } - - # Also skip the "include .depend" that we insert. If we - # don't do this, it is possible to have a bunch of these - # inserted into the output when we read an unmangled Makefile - next if( m/^include .depend/ ); - - # Print the non-dependency info to the temporary Makefile - print MF $_; - } -} - -# Tell our new Makefile to include the dependency file -print MF "include .depend\n"; - -# Close the two output files... -close(DF); -close(MF); - -# Unlink (remove) the original Makefile and rename our -# temporary file. There's obviously room for error checking -# here but we've got the Makefile checked into some revision -# control system anyway. Don't we? - -unlink("Makefile"); -rename("Makefile.tmp","Makefile"); - -exit(0); diff --git a/docs/tutorials/005/handler b/docs/tutorials/005/handler deleted file mode 100644 index d987f4c34ff..00000000000 --- a/docs/tutorials/005/handler +++ /dev/null @@ -1,81 +0,0 @@ - -1. #include "ace/SOCK_Acceptor.h" -2. #include "ace/Reactor.h" - - -3. class Logging_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> - { - - public: - -4. Logging_Handler (void) - { - } - -5. virtual void destroy (void) - { -6. g_reactor->cancel_timer (this); -7. this->peer ().close (); - } - -8. virtual int open (void *) - { -9. ACE_INET_Addr addr; - -10. if (this->peer ().get_remote_addr (addr) == -1) -11. return -1; -12. else - { -13. ACE_OS::strncpy (this->peer_name_, addr.get_host_name (), MAXHOSTNAMELEN + 1); - -14. if (g_reactor->register_handler(this, ACE_Event_Handler::READ_MASK) == -1) -15. ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1); - -16. else if (g_reactor->schedule_timer (this, (const void *) this, ACE_Time_Value (2), ACE_Time_Value (2)) == -1) -17. ACE_ERROR_RETURN ((LM_ERROR, "can'(%P|%t) t register with reactor\n"), -1); - -18. else -19. ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", this->peer_name_)); - -20. return 0; - } - } - -21. virtual int close (u_long) - { -22. this->destroy (); -23. return 0; - } - - protected: - -24. virtual int handle_input (ACE_HANDLE) - { -25. char buf[128]; -26. memset(buf,0,sizeof(buf)); - -27. switch( this->peer().recv(buf,sizeof buf) ) - { -28. case -1: -29. ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client logger"), -1); -30. case 0: -31. ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing log daemon (fd = %d)\n", this->get_handle ()), -1); -32. default: -33. ACE_DEBUG ((LM_DEBUG, "(%P|%t) from client: %s",buf)); - } - -34. return 0; - } - -35. virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg) - { -36. ACE_ASSERT (arg == this); -37. ACE_DEBUG ((LM_DEBUG, "(%P|%t) handling timeout from this = %u\n", this)); -38. return 0; - } - - private: - -39. char peer_name_[MAXHOSTNAMELEN + 1]; - - }; diff --git a/docs/tutorials/005/main b/docs/tutorials/005/main deleted file mode 100644 index 36c67561463..00000000000 --- a/docs/tutorials/005/main +++ /dev/null @@ -1,36 +0,0 @@ -1. #include "ace/Reactor.h" - -2. ACE_Reactor * g_reactor; - -3. static sig_atomic_t finished = 0; -4. extern "C" void handler (int) { finished = 1; } - -5. static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -6. int main (int argc, char *argv[]) - { -7. g_reactor = new ACE_Reactor; - - // Acceptor factory. -8. Logging_Acceptor peer_acceptor; - -9. if (peer_acceptor.open (ACE_INET_Addr (PORT)) == -1) -10. ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - -11. else if (g_reactor->register_handler (&peer_acceptor, ACE_Event_Handler::READ_MASK) == -1) -12. ACE_ERROR_RETURN ((LM_ERROR, "registering service with ACE_Reactor\n"), -1); - -13. ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - // Run forever, performing logging service. - -14. ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server logging daemon\n")); - - // Perform logging service until QUIT_HANDLER receives SIGINT. -15. while ( !finished ) -16. g_reactor->handle_events (); - -17. ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server logging daemon\n")); - -18. return 0; - } diff --git a/docs/tutorials/005/page01.html b/docs/tutorials/005/page01.html deleted file mode 100644 index 60ae178abf3..00000000000 --- a/docs/tutorials/005/page01.html +++ /dev/null @@ -1,38 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>In this tutorial, we're going to flash-back to the simple server we -created a while back. We'll create a very simple server where everything -takes place in one thread. Once we have a solid understanding there, -we'll move on to the next tutorial where we begin to introduce concurrency -concepts. - -<P>There are four C++ source files in this tutorial: server.cpp, -client_acceptor.h, client_handler.h and client_handler.cpp. I'll -talk about each of these in turn with the usual color commentary as we -go. In addition, I'll briefly discuss the Makefile and a short perl -script I've added. - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page02.html">Continue -This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page02.html b/docs/tutorials/005/page02.html deleted file mode 100644 index 7d268e8bd00..00000000000 --- a/docs/tutorials/005/page02.html +++ /dev/null @@ -1,201 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>We begin with <I><A HREF="server.cpp">server.cpp</A></I>. - -<P> -<HR WIDTH="100%"> - -<P><FONT FACE="Arial,Helvetica">// $Id: server.cpp,v 1.5 1998/08/29 21:57:32 -jcej Exp $</FONT><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#include "client_acceptor.h"</FONT><FONT FACE="Arial,Helvetica"></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><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><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><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">static const u_short PORT = ACE_DEFAULT_SERVER_PORT;</FONT><FONT FACE="Arial,Helvetica"></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><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><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Here, we know -that the open was successful. If it had failed, we would</FONT> -<BR><FONT FACE="Arial,Helvetica"> have exited above. -A nice side-effect of the open() is that we're already</FONT> -<BR><FONT FACE="Arial,Helvetica"> registered with -the reactor we provided it.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></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><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting -down server daemon\n"));</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> return 0;</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT> - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page03.html">Continue -This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page03.html b/docs/tutorials/005/page03.html deleted file mode 100644 index fb8acc3e913..00000000000 --- a/docs/tutorials/005/page03.html +++ /dev/null @@ -1,94 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Now, let's take a look at <I><A HREF="client_acceptor.h">client_acceptor.h</A></I>. -Since I went on about how it does all the work of letting clients connect -to us, it must be rather complext. Right? Wrong. - -<P>The more you use ACE, the more you'll find that they've already taken -care of most details for you. With respect to the acceptance of client -connections: there just aren't that many ways to do it! The -ACE team has chosen an approach and created a C++ template that does -all of the work for you. All you're required to do is provide it -with an object type to instantiate when a new connection arrives. - -<P> -<HR WIDTH="100%"> - -<P><FONT FACE="Arial,Helvetica">// $Id$</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#ifndef CLIENT_ACCEPTOR_H</FONT> -<BR><FONT FACE="Arial,Helvetica">#define CLIENT_ACCEPTOR_H</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> The ACE_Acceptor<> template lives -in the ace/Acceptor.h header file.</FONT> -<BR><FONT FACE="Arial,Helvetica"> You'll find a very consitent naming -convention between the ACE objects</FONT> -<BR><FONT FACE="Arial,Helvetica"> and the headers where they can be -found. In general, the ACE object</FONT> -<BR><FONT FACE="Arial,Helvetica"> <I>ACE_Foobar</I> will be found -in <I>ace/Foobar.h</I>.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#include "ace/Acceptor.h"</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Since we want to work with sockets, -we'll need a SOCK_Acceptor to allow</FONT> -<BR><FONT FACE="Arial,Helvetica"> the clients to connect to us.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">#include "ace/SOCK_Acceptor.h"</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> The Client_Handler object we develop -will be used to handle clients</FONT> -<BR><FONT FACE="Arial,Helvetica"> once they're connected. The -ACE_Acceptor<> template's first parameter</FONT> -<BR><FONT FACE="Arial,Helvetica"> requires such an object. In -some cases, you can get by with just a</FONT> -<BR><FONT FACE="Arial,Helvetica"> forward declaration on the class, -in others you have to have the whole</FONT> -<BR><FONT FACE="Arial,Helvetica"> thing.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> Parameterize the ACE_Acceptor<> -such that it will listen for socket</FONT> -<BR><FONT FACE="Arial,Helvetica"> connection attempts and create Client_Handler -objects when they happen.</FONT> -<BR><FONT FACE="Arial,Helvetica"> In Tutorial 001, we wrote the basic -acceptor logic on our own before</FONT> -<BR><FONT FACE="Arial,Helvetica"> we realized that ACE_Acceptor<> -was available. You'll get spoiled using</FONT> -<BR><FONT FACE="Arial,Helvetica"> the ACE templates because they take -away a lot of the tedious details!</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">typedef ACE_Acceptor < Client_Handler, -ACE_SOCK_ACCEPTOR > Client_Acceptor;</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#endif // CLIENT_ACCEPTOR_H</FONT> - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page04.html b/docs/tutorials/005/page04.html deleted file mode 100644 index 2a526c22911..00000000000 --- a/docs/tutorials/005/page04.html +++ /dev/null @@ -1,192 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Ok, so we've got a main() loop that sets up the acceptor and we've seen -how easy it is to create the acceptor object. So far, we've hardly -written any code at all. Well, that's just about to change... - -<P>First, we look at <I><A HREF="client_handler.h">client_handler.h</A></I> -for the declaration of the Client_Handler object. Then we look at -the definition where all of the real work of the application takes place. - -<P> -<HR WIDTH="100%"> - -<P><FONT FACE="Arial,Helvetica">// $Id$</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#ifndef CLIENT_HANDLER_H</FONT> -<BR><FONT FACE="Arial,Helvetica">#define CLIENT_HANDLER_H</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Our client handler must exist -somewhere in the ACE_Event_Handler object</FONT> -<BR><FONT FACE="Arial,Helvetica"> hierarchy. This is -a requirement of the ACE_Reactor because it maintains</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_Event_Handler pointers -for each registered event handler. You could</FONT> -<BR><FONT FACE="Arial,Helvetica"> derive our Client_Handler -directly from ACE_Event_Handler but you still have</FONT> -<BR><FONT FACE="Arial,Helvetica"> to have an ACE_SOCK_Stream -for the actually connection. With a direct</FONT> -<BR><FONT FACE="Arial,Helvetica"> derivative of ACE_Event_Handler, -you'll have to contain and maintain an</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_SOCK_Stream instance -yourself. With ACE_Svc_Handler (which is a</FONT> -<BR><FONT FACE="Arial,Helvetica"> derivative of ACE_Event_Handler) -some of those details are handled for you.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#include "ace/Svc_Handler.h"</FONT> -<BR><FONT FACE="Arial,Helvetica">#include "ace/SOCK_Stream.h"</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Another feature of ACE_Svc_Handler -is it's ability to present the ACE_Task<></FONT> -<BR><FONT FACE="Arial,Helvetica"> interface as well. -That's what the ACE_NULL_SYNCH parameter below is all</FONT> -<BR><FONT FACE="Arial,Helvetica"> about. That's beyond -our scope here but we'll come back to it in the next</FONT> -<BR><FONT FACE="Arial,Helvetica"> tutorial when we start looking -at concurrency options.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">class Client_Handler : public ACE_Svc_Handler -< ACE_SOCK_STREAM, ACE_NULL_SYNCH ></FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica">public:</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> // Constructor...</FONT> -<BR><FONT FACE="Arial,Helvetica"> Client_Handler (void);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> The destroy() -method is our preferred method of destruction. We could</FONT> -<BR><FONT FACE="Arial,Helvetica"> have overloaded -the <i>delete</i> operator but that is neither easy nor</FONT> -<BR><FONT FACE="Arial,Helvetica"> intuitive (at -least to me). Instead, we provide a new method of</FONT> -<BR><FONT FACE="Arial,Helvetica"> destruction and -we make our destructor protected so that only ourselves,</FONT> -<BR><FONT FACE="Arial,Helvetica"> our derivatives -and our friends can <i>delete</i> us. It's a nice</FONT> -<BR><FONT FACE="Arial,Helvetica"> compromise.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> void destroy (void);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Most ACE objects -have an open() method. That's how you make them ready</FONT> -<BR><FONT FACE="Arial,Helvetica"> to do work. -ACE_Event_Handler has a virtual open() method which allows us</FONT> -<BR><FONT FACE="Arial,Helvetica"> to create this -overrride. ACE_Acceptor<> will invoke this method after</FONT> -<BR><FONT FACE="Arial,Helvetica"> creating a new -Client_Handler when a client connects. Notice that the</FONT> -<BR><FONT FACE="Arial,Helvetica"> parameter to -open() is a void*. It just so happens that the pointer</FONT> -<BR><FONT FACE="Arial,Helvetica"> points to the -acceptor which created us. You would like for the parameter</FONT> -<BR><FONT FACE="Arial,Helvetica"> to be an ACE_Acceptor<>* -but since ACE_Event_Handler is generic, that</FONT> -<BR><FONT FACE="Arial,Helvetica"> would tie it -too closely to the ACE_Acceptor<> set of objects. In our</FONT> -<BR><FONT FACE="Arial,Helvetica"> definition of -open() you'll see how we get around that.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> int open (void *_acceptor);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> When there is -activity on a registered handler, the handle_input() method</FONT> -<BR><FONT FACE="Arial,Helvetica"> of the handler -will be invoked. If that method returns an error code (eg</FONT> -<BR><FONT FACE="Arial,Helvetica"> -- -1) then the -reactor will invoke handle_close() to allow the object to</FONT> -<BR><FONT FACE="Arial,Helvetica"> clean itself -up. Since an event handler can be registered for more than</FONT> -<BR><FONT FACE="Arial,Helvetica"> one type of callback, -the callback mask is provided to inform</FONT> -<BR><FONT FACE="Arial,Helvetica"> handle_close() -exactly which method failed. That way, you don't have to</FONT> -<BR><FONT FACE="Arial,Helvetica"> maintain state -information between your handle_* method calls. The _handle</FONT> -<BR><FONT FACE="Arial,Helvetica"> parameter is -explained below...</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> int handle_close (ACE_HANDLE _handle, -ACE_Reactor_Mask _mask);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">protected:</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> When we register -with the reactor, we're going to tell it that we want to</FONT> -<BR><FONT FACE="Arial,Helvetica"> be notified of -READ events. When the reactor sees that there is read</FONT> -<BR><FONT FACE="Arial,Helvetica"> activity for -us, our handle_input() will be invoked. The <i>_handle</i></FONT> -<BR><FONT FACE="Arial,Helvetica"> provided is the -handle (file descriptor in Unix) of the actual connection</FONT> -<BR><FONT FACE="Arial,Helvetica"> causing the activity. -Since we're derived from ACE_Svc_Handler<> and it</FONT> -<BR><FONT FACE="Arial,Helvetica"> maintains it's -own peer (ACE_SOCK_Stream) object, this is redundant for</FONT> -<BR><FONT FACE="Arial,Helvetica"> us. However, -if we had been derived directly from ACE_Event_Handler, we</FONT> -<BR><FONT FACE="Arial,Helvetica"> may have chosen -not to contain the peer. In that case, the <i>_handle</i></FONT> -<BR><FONT FACE="Arial,Helvetica"> would be important -to us for reading the client's data.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> int handle_input (ACE_HANDLE _handle);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> This has nothing -at all to do with ACE. I've added this here as a worker</FONT> -<BR><FONT FACE="Arial,Helvetica"> function which -I will call from handle_input(). That allows me to</FONT> -<BR><FONT FACE="Arial,Helvetica"> introduce concurrencly -in later tutorials with a no changes to the worker</FONT> -<BR><FONT FACE="Arial,Helvetica"> function. -You can think of process() as application-level code and</FONT> -<BR><FONT FACE="Arial,Helvetica"> everything elase -as application-framework code.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> int process (char *_rdbuf, int -_rdbuf_len);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> We don't really -do anything in our destructor but we've declared it to be</FONT> -<BR><FONT FACE="Arial,Helvetica"> protected to -prevent casual deletion of this object. As I said above, I</FONT> -<BR><FONT FACE="Arial,Helvetica"> really would -prefer that everyone goes through the destroy() method to get</FONT> -<BR><FONT FACE="Arial,Helvetica"> rid of us.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> ~Client_Handler (void);</FONT> -<BR><FONT FACE="Arial,Helvetica">};</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#endif // CLIENT_HANDLER_H</FONT> - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page05.html b/docs/tutorials/005/page05.html deleted file mode 100644 index 117366b5af3..00000000000 --- a/docs/tutorials/005/page05.html +++ /dev/null @@ -1,385 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Now we're finally at <I><A HREF="client_handler.cpp">client_handler.cpp</A></I> -where we have to write some code. This file has more code than the -rest of the application all together. - -<P> -<HR WIDTH="100%"> -<BR> -<BR> <FONT FACE="Arial,Helvetica">// $Id$</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> In client_handler.h I alluded -to the fact that we'll mess around with a</FONT> -<BR><FONT FACE="Arial,Helvetica"> Client_Acceptor pointer. -To do so, we need the Client_Acceptor object</FONT> -<BR><FONT FACE="Arial,Helvetica"> declaration.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> We know that including client_handler.h -is redundant because</FONT> -<BR><FONT FACE="Arial,Helvetica"> client_acceptor.h includes -it. Still, the sentry prevents double-inclusion</FONT> -<BR><FONT FACE="Arial,Helvetica"> from causing problems and -it's sometimes good to be explicit about what</FONT> -<BR><FONT FACE="Arial,Helvetica"> we're using.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> On the other hand, we don't -directly include any ACE header files here.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> Our constructor doesn't do -anything. That's generally a good idea. Unless</FONT> -<BR><FONT FACE="Arial,Helvetica"> you want to start throwing -exceptions, there isn't a really good way to</FONT> -<BR><FONT FACE="Arial,Helvetica"> indicate that a constructor -has failed. If I had my way, I'd have a boolean</FONT> -<BR><FONT FACE="Arial,Helvetica"> return code from it that -would cause <I>new</I> to return 0 if I failed. Oh</FONT> -<BR><FONT FACE="Arial,Helvetica"> well...</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> Our destructor doesn't do -anything either. That is also by design.</FONT> -<BR><FONT FACE="Arial,Helvetica"> Remember, we really want -folks to use destroy() to get rid of us. If that's</FONT> -<BR><FONT FACE="Arial,Helvetica"> so, then there's nothing -left to do when the destructor gets invoked.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> The much talked about destroy() -method! The reason I keep going on about</FONT> -<BR><FONT FACE="Arial,Helvetica"> this is because it's just -a Bad Idea (TM) to do real work inside of a</FONT> -<BR><FONT FACE="Arial,Helvetica"> destructor. Although -this method is <I>void</I>, it really should return</FONT> -<BR><FONT FACE="Arial,Helvetica"> <I>int</I> so that it can -tell the caller there was a problem. Even as</FONT> -<BR><FONT FACE="Arial,Helvetica"> <I>void</I> you could at -least throw an exception which you would never want</FONT> -<BR><FONT FACE="Arial,Helvetica"> to do in a destructor.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">void Client_Handler::destroy (void)</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> We probably got -here because of an error on the stream, so the peer</FONT> -<BR><FONT FACE="Arial,Helvetica"> connection is -probably already closed. Still... there are other ways to</FONT> -<BR><FONT FACE="Arial,Helvetica"> get here and -closing a closed peer doesn't hurt.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> this->peer ().close ();</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Tell the reactor -to forget all about us. Notice that we use the same args</FONT> -<BR><FONT FACE="Arial,Helvetica"> here that we -use in the open() method to register ourselves. In addition,</FONT> -<BR><FONT FACE="Arial,Helvetica"> we use the DONT_CALL -flag to prevent handle_close() being called. Since we</FONT> -<BR><FONT FACE="Arial,Helvetica"> likely got here -due to handle_close(), that could cause a bit of nasty</FONT> -<BR><FONT FACE="Arial,Helvetica"> recursion!</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> this->reactor ()->remove_handler -(this,</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> This is how we're -able to tell folks not to use <I>delete</I>. By deleting</FONT> -<BR><FONT FACE="Arial,Helvetica"> our own instance, -we take care of memory leaks after ensuring</FONT> -<BR><FONT FACE="Arial,Helvetica"> that the object -is shut down correctly.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> 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"> As mentioned before, the -open() method is called by the Client_Acceptor when</FONT> -<BR><FONT FACE="Arial,Helvetica"> a new client connection has -been accepted. The Client_Acceptor instance</FONT> -<BR><FONT FACE="Arial,Helvetica"> pointer is cast to a void* -and given to us here. We'll use that to avoid</FONT> -<BR><FONT FACE="Arial,Helvetica"> some global data...</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">int Client_Handler::open (void *_acceptor)</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Convert the void* -to a Client_Acceptor*. You should probably use those</FONT> -<BR><FONT FACE="Arial,Helvetica"> fancy new C++ -cast operators but I can never remember how/when to do so.</FONT> -<BR><FONT FACE="Arial,Helvetica"> Since you can -cast just about anything around a void* without compiler</FONT> -<BR><FONT FACE="Arial,Helvetica"> warnings be very -sure of what you're doing when you do this kind of thing.</FONT> -<BR><FONT FACE="Arial,Helvetica"> That's where -the new-style cast operators can save you.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> Client_Acceptor *acceptor = (Client_Acceptor -*) _acceptor;</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Our reactor reference -will be set when we register ourselves but I decided</FONT> -<BR><FONT FACE="Arial,Helvetica"> to go ahead and -set it here. No good reason really...</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> this->reactor (acceptor->reactor -());</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> We need this -to store the address of the client that we are now connected</FONT> -<BR><FONT FACE="Arial,Helvetica"> to. We'll -use it later to display a debug message.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_INET_Addr addr;</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Our ACE_Svc_Handler -baseclass gives us the peer() method as a way to</FONT> -<BR><FONT FACE="Arial,Helvetica"> access our underlying -ACE_SOCK_Stream. On that object, we can invoke the</FONT> -<BR><FONT FACE="Arial,Helvetica"> get_remote_addr() -method to get get an ACE_INET_Addr having our client's</FONT> -<BR><FONT FACE="Arial,Helvetica"> address information. -As with most ACE methods, we'll get back (and return)</FONT> -<BR><FONT FACE="Arial,Helvetica"> a -1 if there -was any kind of error. Once we have the ACE_INET_Addr, we</FONT> -<BR><FONT FACE="Arial,Helvetica"> can query it -to find out the clien's host name, TCP/IP address, TCP/IP</FONT> -<BR><FONT FACE="Arial,Helvetica"> port value and -so forth. One word of warning: the get_host_name()</FONT> -<BR><FONT FACE="Arial,Helvetica"> method of ACE_INET_Addr -may return you an empty string if your name server</FONT> -<BR><FONT FACE="Arial,Helvetica"> can't resolve -it. On the other hand, get_host_addr() will always give you</FONT> -<BR><FONT FACE="Arial,Helvetica"> the dotted-decimal -string representing the TCP/IP address.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> if (this->peer ().get_remote_addr -(addr) == -1)</FONT> -<BR><FONT FACE="Arial,Helvetica"> {</FONT> -<BR><FONT FACE="Arial,Helvetica"> return --1;</FONT> -<BR><FONT FACE="Arial,Helvetica"> }</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> If we managed -to get the client's address then we're connected to a real</FONT> -<BR><FONT FACE="Arial,Helvetica"> and valid client. -I suppose that in some cases, the client may connect</FONT> -<BR><FONT FACE="Arial,Helvetica"> and disconnect -so quickly that it is invalid by the time we get here. In</FONT> -<BR><FONT FACE="Arial,Helvetica"> any case, the -test above should always be done to ensure that the</FONT> -<BR><FONT FACE="Arial,Helvetica"> connection is -worth keeping.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> Now, regiser ourselves -with a reactor and tell that reactor that we want</FONT> -<BR><FONT FACE="Arial,Helvetica"> to be notified -when there is something to read. Remember, we took our</FONT> -<BR><FONT FACE="Arial,Helvetica"> reactor value -from the acceptor which created us in the first place.</FONT> -<BR><FONT FACE="Arial,Helvetica"> Since we're exploring -a single-threaded implementation, this is the</FONT> -<BR><FONT FACE="Arial,Helvetica"> correct thing -to do.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> if (this->reactor ()->register_handler -(this, ACE_Event_Handler::READ_MASK) == -1)</FONT> -<BR><FONT FACE="Arial,Helvetica"> {</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_ERROR_RETURN -((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1);</FONT> -<BR><FONT FACE="Arial,Helvetica"> }</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Here, we use -the ACE_INET_Addr object to print a message with the name of</FONT> -<BR><FONT FACE="Arial,Helvetica"> the client we're -connected to. Again, it is possible that you'll get an</FONT> -<BR><FONT FACE="Arial,Helvetica"> empty string -for the host name if your DNS isn't configured correctly or</FONT> -<BR><FONT FACE="Arial,Helvetica"> if there is some -other reason that a TCP/IP addreess cannot be converted</FONT> -<BR><FONT FACE="Arial,Helvetica"> into a host name.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> 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"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Always return -zero on success.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> 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"> In the open() method, we -registered with the reactor and requested to be</FONT> -<BR><FONT FACE="Arial,Helvetica"> notified when there is data -to be read. When the reactor sees that activity</FONT> -<BR><FONT FACE="Arial,Helvetica"> it will invoke this handle_input() -method on us. As I mentioned, the _handle</FONT> -<BR><FONT FACE="Arial,Helvetica"> parameter isn't useful to -us but it narrows the list of methods the reactor</FONT> -<BR><FONT FACE="Arial,Helvetica"> has to worry about and the -list of possible virtual functions we would have</FONT> -<BR><FONT FACE="Arial,Helvetica"> to override.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Some compilers -don't like it when you fail to use a parameter. This macro</FONT> -<BR><FONT FACE="Arial,Helvetica"> will keep 'em -quiet for you.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_UNUSED_ARG (_handle);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Now, we create -and initialize a buffer for receiving the data. Since this</FONT> -<BR><FONT FACE="Arial,Helvetica"> is just a simple -test app, we'll use a small buffer size.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> char buf[128];</FONT> -<BR><FONT FACE="Arial,Helvetica"> memset (buf, 0, sizeof (buf));</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Invoke the process() -method with a pointer to our data area. We'll let</FONT> -<BR><FONT FACE="Arial,Helvetica"> that method worry -about interfacing with the data. You might choose to go</FONT> -<BR><FONT FACE="Arial,Helvetica"> ahead and read -the data and then pass the result to process(). However,</FONT> -<BR><FONT FACE="Arial,Helvetica"> application logic -may require that you read a few bytes to determine what</FONT> -<BR><FONT FACE="Arial,Helvetica"> else to read... -It's best if we push that all into the application-logic</FONT> -<BR><FONT FACE="Arial,Helvetica"> level.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> 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"> If we return -1 out of handle_input() -or if the reactor sees other problems</FONT> -<BR><FONT FACE="Arial,Helvetica"> with us then handle_close() -will be called. It uses our destroy() method to</FONT> -<BR><FONT FACE="Arial,Helvetica"> shut us down cleanly and -get rid of our instance.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> ACE_UNUSED_ARG (_handle);</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_UNUSED_ARG (_mask);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> this->destroy ();</FONT> -<BR><FONT FACE="Arial,Helvetica"> 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"> And, at last, we get to the -application-logic level. Out of everything</FONT> -<BR><FONT FACE="Arial,Helvetica"> we've done so far, this is -the only thing that really has anything to do</FONT> -<BR><FONT FACE="Arial,Helvetica"> with what your application -will do. In this method we will read and process</FONT> -<BR><FONT FACE="Arial,Helvetica"> the client's data. -In a real appliation, you will probably have a bit more</FONT> -<BR><FONT FACE="Arial,Helvetica"> in main() to deal with command -line options but after that point, all of the</FONT> -<BR><FONT FACE="Arial,Helvetica"> action takes place here.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</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"> /*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Using the buffer -provided for us, we read the data from the client. If</FONT> -<BR><FONT FACE="Arial,Helvetica"> there is a read -error (eg -- recv() returns -1) then it's a pretty good</FONT> -<BR><FONT FACE="Arial,Helvetica"> bet that the -connection is gone. Likewise, if we read zero bytes then</FONT> -<BR><FONT FACE="Arial,Helvetica"> something wrong -has happened. The reactor wouldn't have called us if</FONT> -<BR><FONT FACE="Arial,Helvetica"> there wasn't -some kind of read activity but there wouldn't be activity if</FONT> -<BR><FONT FACE="Arial,Helvetica"> there were no -bytes to read...</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> On the other hand, -if we got some data then we can display it in a debug</FONT> -<BR><FONT FACE="Arial,Helvetica"> message for everyone -to see.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica"> switch (this->peer ().recv (_rdbuf, -_rdbuf_len))</FONT> -<BR><FONT FACE="Arial,Helvetica"> {</FONT> -<BR><FONT FACE="Arial,Helvetica"> case -1:</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_ERROR_RETURN -((LM_ERROR, "(%P|%t) %p bad read\n", "client"), -1);</FONT> -<BR><FONT FACE="Arial,Helvetica"> case 0:</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_ERROR_RETURN -((LM_ERROR, "(%P|%t) closing daemon (fd = %d)\n", this->get_handle ()), --1);</FONT> -<BR><FONT FACE="Arial,Helvetica"> default:</FONT> -<BR><FONT FACE="Arial,Helvetica"> ACE_DEBUG -((LM_DEBUG, "(%P|%t) from client: %s", _rdbuf));</FONT> -<BR><FONT FACE="Arial,Helvetica"> }</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> return 0;</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P> -<HR WIDTH="100%"> - -<P>That's the last of the C++ code. On the final two pages I'll -go over the Makefile and a short perl script I wrote to "assist" the -Makefile. Please... Continue... - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page06.html b/docs/tutorials/005/page06.html deleted file mode 100644 index 95a341cf0ea..00000000000 --- a/docs/tutorials/005/page06.html +++ /dev/null @@ -1,195 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Before we go, I wanted you to see the <A HREF="Makefile">Makefile</A>. - -<P> -<HR WIDTH="100%"> -<BR> -<UL><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> -<BR><FONT FACE="Arial,Helvetica"># -$Id$</FONT> -<BR><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> - -<P><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> -<BR><FONT FACE="Arial,Helvetica"># -Local macros</FONT> -<BR><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> - -<P><FONT FACE="Arial,Helvetica"># You can generally find a Makefile in -the ACE examples, tests or the library</FONT> -<BR><FONT FACE="Arial,Helvetica"># itself that will satisfy our application -needs. This one was taken from</FONT> -<BR><FONT FACE="Arial,Helvetica"># one of the examples.</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Define the name of the binary we want to create. There has to be</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# a CPP file $(BIN).cpp but it doesn't necessarily have to have your</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# main() in it. Most of the time, though, it will.</FONT> -<BR><FONT FACE="Arial,Helvetica">BIN = server</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Few applications will have a single source file. We use the FILES</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# macro to build up a list of additional files to compile. Notice</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# that we leave off the extension just as with BIN</FONT> -<BR><FONT FACE="Arial,Helvetica">FILES =</FONT> -<BR><FONT FACE="Arial,Helvetica">FILES += client_handler</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# The BUILD macro is used by the ACE makefiles. Basically, it tells</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# the system what to build. I don't really know what VBIN is other</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# than it is constructed from the value of BIN. Just go with it...</FONT> -<BR><FONT FACE="Arial,Helvetica">BUILD = $(VBIN)</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Here we use some GNU make extensions to build the SRC macro. Basically,</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# we're just adding .cpp to the value of BIN and for each entry of the</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# FILES macro.</FONT> -<BR><FONT FACE="Arial,Helvetica">SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix -.cpp,$(FILES))</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# This is used by my Indent target below. It's not a part of standard</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# ACE and you don't need it yourself.</FONT> -<BR><FONT FACE="Arial,Helvetica">HDR = *.h</FONT> - -<P><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> -<BR><FONT FACE="Arial,Helvetica"># -Include macros and targets</FONT> -<BR><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# This is where the real power lies! These included makefile components</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# are similar to the C++ templates in ACE. That is, they do a tremendous</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# amount of work for you and all you have to do is include them.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# As a matter of fact, in our project, I created a single file named</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# "app.mk" that includes all of these. Our project makefiles then -just</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# need to include app.mk to get everything they need.</FONT> - -<P><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU</FONT> -<BR><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/macros.GNU</FONT> -<BR><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/rules.common.GNU</FONT> -<BR><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU</FONT> -<BR><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU</FONT> -<BR><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU</FONT> -<BR><FONT FACE="Arial,Helvetica">include $(ACE_ROOT)/include/makeinclude/rules.local.GNU</FONT> - -<P><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> -<BR><FONT FACE="Arial,Helvetica"># -Local targets</FONT> -<BR><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Sometimes I like to reformat my code to make it more readable. -This is</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# more useful for the comments than anything else. Unfortunately, -the</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# "indent" program doesn't quite grok C++ so I have to post-process it's</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# output just a bit.</FONT> -<BR><FONT FACE="Arial,Helvetica">Indent : #</FONT> -<BR><FONT FACE="Arial,Helvetica"> -for i in $(SRC) $(HDR) ; do \</FONT> -<BR><FONT FACE="Arial,Helvetica"> -indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \</FONT> -<BR><FONT FACE="Arial,Helvetica"> -sed -e 's/: :/::/g' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> --e 's/^.*\(public:\)/\1/' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> --e 's/^.*\(protected:\)/\1/' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> --e 's/^.*\(private:\)/\1/' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> --e 's/:\(public\)/ : \1/' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> --e 's/:\(protected\)/ : \1/' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> --e 's/:\(private\)/ : \1/' \</FONT> -<BR><FONT FACE="Arial,Helvetica"> -> $$i~ ;\</FONT> -<BR><FONT FACE="Arial,Helvetica"> -mv $$i~ $$i ;\</FONT> -<BR><FONT FACE="Arial,Helvetica"> -done</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# One of the targets in the ACE makefiles is "depend". It will invoke</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# your compiler in a way that will generate a list of dependencies for</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# you. This is a great thing! Unfortunately, it puts all of -that mess</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# directly into the Makefile. I prefer my Makefile to stay clean -and</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# uncluttered. The perl script referenced here pulls the dependency</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# stuff back out of the Makefile and into a file ".depend" which we then</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# include just like the makefile components above.</FONT> -<BR><FONT FACE="Arial,Helvetica">Depend : depend</FONT> -<BR><FONT FACE="Arial,Helvetica"> -perl fix.Makefile</FONT> -<BR><FONT FACE="Arial,Helvetica"> </FONT> -<BR><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> -<BR><FONT FACE="Arial,Helvetica"># -Dependencies</FONT> -<BR><FONT FACE="Arial,Helvetica">#----------------------------------------------------------------------------</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Don't put anything below here. Between the "depend" target and -fix.Makefile</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# it's guaranteed to be lost!</FONT> - -<P><FONT FACE="Arial,Helvetica"> -# This is inserted by the fix.Makefile script</FONT> -<BR><FONT FACE="Arial,Helvetica">include .depend</FONT></UL> - -<HR WIDTH="100%"> - -<P>Remember, make wants to see tabs leading all of the directives. -If you do a cut/paste job you'll need to convert all leading spaces to -tabs or make will be very unhappy with you. - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page07.html">Continue This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page07.html b/docs/tutorials/005/page07.html deleted file mode 100644 index 069f94be956..00000000000 --- a/docs/tutorials/005/page07.html +++ /dev/null @@ -1,123 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>And last (and probably least) is the <A HREF="fix.Makefile">perl script</A> -that pulls the dependency stuff out of Makefile and into .depend. - -<P> -<HR WIDTH="100%"> -<BR> <FONT FACE="Arial,Helvetica">#!/usr/bin/perl</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Open the Makefile that has been mangled by 'make depend'</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# and suck it into a perl array.</FONT> -<BR><FONT FACE="Arial,Helvetica">open(IF,"<Makefile") || die;</FONT> -<BR><FONT FACE="Arial,Helvetica">@makefile = <IF>;</FONT> -<BR><FONT FACE="Arial,Helvetica">close(IF);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Now open our .depend file and a temporary Makefile.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# We'll split the original Makefile between these two.</FONT> -<BR><FONT FACE="Arial,Helvetica">open(DF,">.depend") || die;</FONT> -<BR><FONT FACE="Arial,Helvetica">open(MF,">Makefile.tmp") || die;</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# For each line we read out of the original file...</FONT> -<BR><FONT FACE="Arial,Helvetica">foreach (@makefile) {</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# If we're into the dependency section, write the line</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# into the .depend file.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -#</FONT> -<BR><FONT FACE="Arial,Helvetica"> -if( $depend ) {</FONT> -<BR><FONT FACE="Arial,Helvetica"> -print DF $_;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT> -<BR><FONT FACE="Arial,Helvetica"> -else {</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# If we haven't gotten to the dependency section yet</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# then see if the current line is the separator that</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# "make depend" causes to be inserted.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -#</FONT> -<BR><FONT FACE="Arial,Helvetica"> -if( m/^\Q# DO NOT DELETE THIS LINE -- g++dep uses it.\E/ ) {</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# If so, change our "mode" and skip this line.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -++$depend;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -next;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Also skip the "include .depend" that we insert. If we</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# don't do this, it is possible to have a bunch of these</FONT> -<BR><FONT FACE="Arial,Helvetica"> -# inserted into the output when we read an unmangled Makefile</FONT> -<BR><FONT FACE="Arial,Helvetica"> -next if( m/^include .depend/ );</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -# Print the non-dependency info to the temporary Makefile</FONT> -<BR><FONT FACE="Arial,Helvetica"> -print MF $_;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"># Tell our new Makefile to include the -dependency file</FONT> -<BR><FONT FACE="Arial,Helvetica">print MF "include .depend\n";</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"># Close the two output files...</FONT> -<BR><FONT FACE="Arial,Helvetica">close(DF);</FONT> -<BR><FONT FACE="Arial,Helvetica">close(MF);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"># Unlink (remove) the original Makefile -and rename our</FONT> -<BR><FONT FACE="Arial,Helvetica"># temporary file. There's obviously -room for error checking</FONT> -<BR><FONT FACE="Arial,Helvetica"># here but we've got the Makefile checked -into some revision</FONT> -<BR><FONT FACE="Arial,Helvetica"># control system anyway. Don't we?</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">unlink("Makefile");</FONT> -<BR><FONT FACE="Arial,Helvetica">rename("Makefile.tmp","Makefile");</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">exit(0);</FONT> - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page08.html">Continue This Tutorial</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/page08.html b/docs/tutorials/005/page08.html deleted file mode 100644 index 6cc18602049..00000000000 --- a/docs/tutorials/005/page08.html +++ /dev/null @@ -1,53 +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="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>That's it for Tutorial 5. In this tutorial we've built a single-threaded -reactor-based server. We've done a couple of things that aren't exactly -necessary for such an implementation but I plan to build on that as -we explore two other concurrency strategies: thread per connection -and thread pool. - -<P>For reference, here's the file list again: -<UL> -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="client_acceptor.h">client_acceptor.h</A></LI> - -<LI> -<A HREF="client_handler.cpp">client_handler.cpp</A></LI> - -<LI> -<A HREF="client_handler.h">client_handler.h</A></LI> - -<LI> -<A HREF="server.cpp">server.cpp</A></LI> - -<LI> -<A HREF="fix.Makefile">fix.Makefile</A></LI> -</UL> - - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>]</CENTER> - -</BODY> -</HTML> diff --git a/docs/tutorials/005/server.brk b/docs/tutorials/005/server.brk deleted file mode 100644 index ba3d878a1da..00000000000 --- a/docs/tutorials/005/server.brk +++ /dev/null @@ -1,154 +0,0 @@ - -#include "ace/Acceptor.h" -#include "ace/SOCK_Acceptor.h" -#include "ace/Reactor.h" -#include "ace/Thread.h" - - -ACE_Reactor * g_reactor; - -static sig_atomic_t finished = 0; - -class Logging_Handler; - -extern "C" void handler (int) { finished = 1; } - - - -class Reactor_Derived : public ACE_Reactor -{ - -public : - Reactor_Derived() : () - { - counter = 0; - } - - virtual ~Reactor_Derived() - { - cout << "*****Calling the reactor destructor*****" << endl; - } - -private : - friend class Logging_Handler; - - // counter is used to keep track of the number of service handlers - // registered with this reactor (Surely theres a better way ;-) - int counter; -}; - -class Logging_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ - -public: - - Logging_Handler (void) { }; - - virtual void destroy (void) - { - if (this->thread_reactorP->remove_handler(this, - ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL) == -1 - ) - ACE_ERROR_RETURN ((LM_ERROR, "can'(%P|%t) t remove service from reactor\n"), -1); - - // Decrement the handler tracking variable in the reactor to - // indicate this service handler has terminated - --thread_reactorP->counter; - - this->peer ().close (); - delete this; - } - - static void *run_thread(Logging_Handler *this_) - { - Reactor_Derived thread_reactor; - - this_->thread_reactorP = &thread_reactor; - - // Increment our handler counter to account for this service handler - ++thread_reactor.counter; - - if (thread_reactor.register_handler(this_, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR,"can'(%P|%t) t register with reactor\n"), -1); - - while( thread_reactor.counter > 0 ) - { - // If thread_reactor.counter = 0 then we have no more service - // handlers connected to the reactor. We set a timeout value - // of 1 second so that the handle_events loop break out every - // second to check on the count ( because of it blocking - // even when there are no connections we need to do this) - thread_reactor.handle_events(ACE_Time_Value(1,0)); - } - } - - virtual int open (void *) - { - ACE_Thread::spawn(&Logging_Handler::run_thread,this); - return 0; - } - - virtual int close (u_long) - { - this->destroy (); - return 0; - } - -protected: - - virtual 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; - } - - -private: - Reactor_Derived *thread_reactorP; -}; - - -typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor; - - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int main (int argc, char *argv[]) -{ - g_reactor = new ACE_Reactor; - - // Acceptor factory. - Logging_Acceptor peer_acceptor; - - if (peer_acceptor.open (ACE_INET_Addr (PORT)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - - else if (g_reactor->register_handler (&peer_acceptor, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "registering service with ACE_Reactor\n"), -1); - - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - // Run forever, performing logging service. - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server logging daemon\n")); - - // Perform logging service until QUIT_HANDLER receives SIGINT. - while ( !finished ) - g_reactor->handle_events (); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server logging daemon\n")); - - return 0; -} diff --git a/docs/tutorials/005/server.cpp b/docs/tutorials/005/server.cpp deleted file mode 100644 index ee46a9d2b57..00000000000 --- a/docs/tutorials/005/server.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// $Id$ - -/* - 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 "real work". - */ - -#include "client_acceptor.h" - -/* - 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. - */ - -static sig_atomic_t finished = 0; -extern "C" void handler (int) -{ - finished = 1; -} - -/* - 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. - */ - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* - 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. - */ - -int main (int argc, char *argv[]) -{ -/* - 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. - */ - ACE_Reactor reactor; - - /* - 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.) - */ - Client_Acceptor peer_acceptor; - - /* - 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 "well known" - 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. - */ - if (peer_acceptor.open (ACE_INET_Addr (PORT), &reactor) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - - /* - Here, we know that the open was successful. If it had failed, we would - have exited above. A nice side-effect of the open() is that we're already - registered with the reactor we provided it. - */ - - /* - 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 "real" work. Our simple flag-setter doesn't - justify deriving from ACE_Event_Handler and providing a callback function - though. - */ - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - /* - 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. - */ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server daemon\n")); - - /* - This will loop "forever" 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.) - */ - while (!finished) - reactor.handle_events (); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server daemon\n")); - - return 0; -} - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ |