diff options
Diffstat (limited to 'docs/tutorials/004/page01.html')
-rw-r--r-- | docs/tutorials/004/page01.html | 316 |
1 files changed, 0 insertions, 316 deletions
diff --git a/docs/tutorials/004/page01.html b/docs/tutorials/004/page01.html deleted file mode 100644 index a6e69c5eb98..00000000000 --- a/docs/tutorials/004/page01.html +++ /dev/null @@ -1,316 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 004</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 004</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>A much more clever Client</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Ok, so the last time around, we learned how to create a simple client -that can send a chunk of data. A cooler thing to do is to overload -the C++ put operator (<<) to put some data for us. That's what -we're going to do this time. (This tutorial is actually where ACE_IOStream -was born.) - -<P> -<HR WIDTH="100%"> -<PRE>/* - We need the connector object & we also bring in a simple string class. - */ -#include "ace/SOCK_Connector.h" -#include "ace/SString.h" - -/* - In this tutorial, we extend SOCK_Stream by adding a few wrappers - around the send_n() method. - */ -class Client : public ACE_SOCK_Stream -{ - -public: - // Basic constructor - Client(void); - - /* - Construct and open() in one call. This isn't generally a good - idea because you don't have a clean way to inform the caller - when open() fails. (Unless you use C++ exceptions.) - */ - Client( const char * server, u_short port ); - - /* - Open the connection to the server. Notice that this mirrors - the use of ACE_SOCK_Connector. By providing our own open(), - we can hide the connector from our caller & make it's interaction - easier. - */ - int open( const char * server, u_short port ); - - /* - These are necessary if you're going to use the constructor that - invokes open(). - */ - inline int initialized(void) { return initialized_; } - inline int error(void) { return error_; } - - /* - This is where the coolness lies. Most C++ folks are familiar - with "cout << some-data". It's a very handy and easy way to - toss data around. By adding these method calls, we're able - to do the same thing with a socket connection. - */ - Client & operator<<( ACE_SString & str ); - Client & operator<<( char * str ); - Client & operator<<( int n ); - -protected: - unsigned char initialized_; - unsigned char error_; - -}; - -/* - The basic constructor just sets our flags to reasonable values. - */ -Client::Client(void) -{ - initialized_ = 0; - error_ = 0; -} - -/* - This constructor also sets the flags but then calls open(). If the - open() fails, the flags will be set appropriately. Use the two inline - method calls initialized() and error() to check the object state after - using this constructor. - */ -Client::Client( const char * server, u_short port ) -{ - initialized_ = 0; - error_ = 0; - (void)open(server,port); -} - -/* - Open a connection to the server. This hides the use of ACE_SOCK_Connector - from our caller. Since our caller probably doesn't care *how* we connect, - this is a good thing. - */ -int Client::open( const char * server, u_short port ) -{ - /* - This is right out of Tutorial 3. The only thing we've added is to set - the initialized_ member variable on success. - */ - - ACE_SOCK_Connector connector; - ACE_INET_Addr addr (port, server); - - if (connector.connect (*this, addr) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - } - - initialized_ = 1; - - return(0); -} - -/* - The first of our put operators sends a simple string object to the peer. -*/ -Client & Client::operator<<( ACE_SString & str ) -{ - /* - We have to be able to allow: - server << foo << bar << stuff; - - To accomplish that, every << operator must check that the object is - in a valid state before doing work. - */ - - if( initialized() && ! error() ) - { - /* - Get the actual data held in the string object - */ - char * cp = str.rep(); - - /* - Send that data to the peer using send_n() as before. If we have - a problem, we'll set error_ so that subsequent << operations won't - try to use a broken stream. - */ - if( this->send_n(cp,strlen(cp)) == -1 ) - { - error_ = 1; - } - } - else - { - /* - Be sure that error_ is set if somebody tries to use us when - we're not initialized. - */ - error_ = 1; - } - - /* - We have to return a reference to ourselves to allow chaining of - put operations (eg -- "server << foo << bar"). Without the reference, - you would have to do each put operation as a statement. That's OK - but doesn't have the same feel as standard C++ iostreams. - */ - return *this ; -} - -/* -How do you put a char*? We'll take an easy way out and construct an ACE_SString -from the char* and then put that. It would have been more efficient to implement -this with the body of the operator<<(ACE_SString&) method and then express that -method in terms of this one. There's always more than one way to do things! - */ -Client & Client::operator<< ( char * str ) -{ - ACE_SString newStr(str); - - *this << newStr; - - return *this ; - - /* - Notice that we could have been really clever and done: - - return *this << ACE_SString(str); - - That kind of thing just makes debugging a pain though! - */ -} - -/* - ACE_SString and char* are both about the same thing. What do you do about - different datatypes though? - - Do the same thing we did with char* and convert it to ACE_SString where we - already have a << operator defined. - */ -Client & Client::operator<< ( int n ) -{ - /* - Create a character buffer large enough for the largest number. That's - a tough call but 1024 should be quite enough. - */ - char buf[1024]; - - /* - Put the number into our buffer... - */ - ACE_OS::sprintf(buf,"(%d)\n",n); - - /* - And create the ACE_SString that we know how to put. - */ - ACE_SString newStr(buf); - - /* - Send it and... - */ - *this << newStr; - - /* - return ourselves as usual. - */ - return *this; -} - - -/* - Now we pull it all together. Like Tutorial 3, we'll allow command line options. - */ -int main (int argc, char *argv[]) -{ - const char *server_host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST; - u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT; - int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : 4; - - /* - Use the basic constructor since the other isn't really very safe. - */ - Client server; - - /* - Open the server connection. Notice how this is simpler than Tutorial 3 - since we only have to provide a host name and port value. - */ - if( server.open(server_host,server_port) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - } - - for (int i = 0; i < max_iterations; i++) - { - /* - Tell the server which iteration we're on. No more mucking aroudn with - sprintf at this level! It's all hidden from us. - */ - server << "message = " << i+1; - - /* - Everything OK? - */ - if ( server.error() ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send"), -1); - } - else - { - ACE_OS::sleep (1); - } - } - - if (server.close () == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "close"), -1); - } - - return 0; -}</PRE> - -<HR WIDTH="100%"> - -<P>Ok, now we're done with that. As you can see, it really isn't -so hard to create an object that makes sending data much more "natural" -than the typical send() or send_n() invocation. You can even build -up arbitrary objects & do some neat tricks with C++ templates to stream -their data out as well. (We may go into that a little later.) -Of course, writting the full implementation such that these streams are -interchangable with the standard C++ ostreams is quite a bit more difficult. -In addition, there are a lot of optimizations that this client would benefit -from! - -<P>As an exercise to the reader (don't you hate those!) I challenge you -to write the server side of this. You can take a look at IOStream_Test -in the ACE distribution if you get stuck... - -<P>If you want to compile it yourself, here's the <A HREF="client.cpp">source</A>, -the <A HREF="Makefile">Makefile</A>, -and <A HREF="00SetEnv">Environment -settings</A>. - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>]</CENTER> - -</BODY> -</HTML> |