diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 2001-07-01 23:08:52 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 2001-07-01 23:08:52 +0000 |
commit | 8f1d69b7c77cb8537f053c44b3ff84fe7f8e423f (patch) | |
tree | 331e1b3701297c2137a6f480789633195e57e6cc /examples | |
parent | dec09ff8948e05cb91cff9059603dfdfdaef82b2 (diff) | |
download | ATCD-8f1d69b7c77cb8537f053c44b3ff84fe7f8e423f.tar.gz |
ChangeLogTag:Sun Jul 1 11:49:13 2001 Douglas C. Schmidt <schmidt@tango.doc.wustl.edu>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Reactor/Proactor/Makefile | 13 | ||||
-rw-r--r-- | examples/Reactor/Proactor/test_udp_proactor.cpp | 419 | ||||
-rw-r--r-- | examples/Reactor/Proactor/test_udp_proactor.dsp | 102 |
3 files changed, 533 insertions, 1 deletions
diff --git a/examples/Reactor/Proactor/Makefile b/examples/Reactor/Proactor/Makefile index f8140265b84..0b8b847af67 100644 --- a/examples/Reactor/Proactor/Makefile +++ b/examples/Reactor/Proactor/Makefile @@ -8,7 +8,18 @@ # Local macros #---------------------------------------------------------------------------- -BIN = simple_test_proactor test_proactor test_aiosig_ace test_aiocb_ace test_timeout test_timeout_st post_completions test_end_event_loop test_cancel test_proactor2 test_proactor3 +BIN = simple_test_proactor \ + test_proactor \ + test_aiosig_ace \ + test_aiocb_ace \ + test_timeout \ + test_timeout_st \ + post_completions \ + test_end_event_loop \ + test_cancel \ + test_proactor2 \ + test_proactor3 \ + test_udp_proactor #---------------------------------------------------------------------------- # Include macros and targets diff --git a/examples/Reactor/Proactor/test_udp_proactor.cpp b/examples/Reactor/Proactor/test_udp_proactor.cpp new file mode 100644 index 00000000000..88f48937620 --- /dev/null +++ b/examples/Reactor/Proactor/test_udp_proactor.cpp @@ -0,0 +1,419 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// examples +// +// = FILENAME +// test_udp_proactor.cpp +// +// = DESCRIPTION +// This program illustrates how the <ACE_Proactor> can be used to +// implement an application that does asynchronous operations using +// datagrams. +// +// = AUTHOR +// Irfan Pyarali <irfan@cs.wustl.edu> and +// Roger Tragin <r.tragin@computer.org> +// +// ============================================================================ + +#include "ace/Proactor.h" +#include "ace/Asynch_IO.h" +#include "ace/INET_Addr.h" +#include "ace/SOCK_Dgram.h" +#include "ace/Message_Block.h" +#include "ace/Get_Opt.h" + +ACE_RCSID(Proactor, test_udp_proactor, "test_proactor.cpp,v 1.29 2001/02/02 23:41:16 shuston Exp") + +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) || defined (ACE_HAS_AIO_CALLS) + // This only works on Win32 platforms. + +// Host that we're connecting to. +static char *host = 0; + +// Port that we're receiving connections on. +static u_short port = ACE_DEFAULT_SERVER_PORT; + +// Keep track of when we're done. +static int done = 0; + +class Receiver : public ACE_Service_Handler +{ + // = TITLE + // This class will receive data from + // the network connection and dump it to a file. +public: + // = Initialization and termination. + Receiver (void); + ~Receiver (void); + + int open (const ACE_INET_Addr &localAddr); + +protected: + // These methods are called by the framework + + /// This method will be called when an asynchronous read completes on + /// a UDP socket. + virtual void handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result); + +private: + ACE_SOCK_Dgram sockDgram_; + ACE_Asynch_Read_Dgram rd_; + // rd (read dgram): for reading from a UDP socket. + const char* completion_key_; + const char* act_; +}; + +Receiver::Receiver (void) + : completion_key_ ("Receiver Completion Key"), + act_ ("Receiver ACT") +{ +} + +Receiver::~Receiver (void) +{ + sockDgram_.close (); +} + +int +Receiver::open (const ACE_INET_Addr &localAddr) +{ + ACE_DEBUG ((LM_DEBUG, + "%N:%l:Receiver::open called\n")); + + // Create a local UDP socket to receive datagrams. + if (this->sockDgram_.open (localAddr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_SOCK_Dgram::open"), -1); + + // Initialize the asynchronous read. + if (this->rd_.open (*this, + this->sockDgram_.get_handle (), + this->completion_key_, + ACE_Proactor::instance ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_Asynch_Read_Dgram::open"), -1); + + // Create a buffer to read into. We are using scatter/gather to + // read the message header and message body into 2 buffers + + // create a message block to read the message header + ACE_Message_Block* msg = 0; + ACE_NEW_RETURN (msg, ACE_Message_Block (1024), -1); + + // the next line sets the size of the header, even though we + // allocated a the message block of 1k, by setting the size to 20 + // bytes then the first 20 bytes of the reveived datagram will be + // put into this message block. + msg->size (20); // size of header to read is 20 bytes + + // create a message block to read the message body + ACE_Message_Block* body = 0; + ACE_NEW_RETURN (body, ACE_Message_Block (1024), -1); + // The message body will not exceed 1024 bytes, at least not in this test. + + // set body as the cont of msg. This associates the 2 message + // blocks so that a read will fill the first block (which is the + // header) up to size(), and use the cont() block for the rest of + // the data. You can chain up to IOV_MAX message block using this + // method. + msg->cont (body); + + // ok lets do the asynch read + size_t number_of_bytes_recvd = 0; + + int res = rd_.recv (msg, + number_of_bytes_recvd, + 0, + PF_INET, + this->act_); + switch (res) + { + case 0: + // this is a good error. The proactor will call our handler when the + // read has completed. + break; + case 1: + // actually read something, we will handle it in the handler callback + ACE_DEBUG ((LM_DEBUG, "********************\n")); + ACE_DEBUG ((LM_DEBUG, + "%s = %d\n", + "bytes recieved immediately", + number_of_bytes_recvd)); + ACE_DEBUG ((LM_DEBUG, "********************\n")); + res = 0; + break; + case -1: + // Something else went wrong. + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE_Asynch_Read_Dgram::recv")); + // the handler will not get called in this case so lets clean up our msg + msg->release (); + break; + default: + // Something undocumented really went wrong. + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE_Asynch_Read_Dgram::recv")); + msg->release (); + break; + } + + return res; +} + +void +Receiver::handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result) +{ + ACE_DEBUG ((LM_DEBUG, + "handle_read_dgram called\n")); + + ACE_DEBUG ((LM_DEBUG, "********************\n")); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ())); + ACE_INET_Addr peerAddr; + result.remote_address (peerAddr); + ACE_DEBUG ((LM_DEBUG, "%s = %s:%d\n", "peer_address", peerAddr.get_host_addr (), peerAddr.get_port_number ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ())); + ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "act", result.act ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ())); + ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "completion_key", result.completion_key ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ())); + ACE_DEBUG ((LM_DEBUG, "********************\n")); + + if (result.success () && result.bytes_transferred () != 0) + { + // loop through our message block and print out the contents + for (const ACE_Message_Block* msg = result.message_block(); msg != 0; msg = msg->cont ()) + { // use msg->length() to get the number of bytes written to the message + // block. + ACE_DEBUG ((LM_DEBUG, "Buf=[size=<%d>", msg->length ())); + for (u_long i = 0; i < msg->length(); ++i) + ACE_DEBUG ((LM_DEBUG, + "%c", (msg->rd_ptr())[i])); + ACE_DEBUG ((LM_DEBUG, "]\n")); + } + } + + ACE_DEBUG ((LM_DEBUG, + "Receiver completed\n")); + + // No need for this message block anymore. + result.message_block ()->release (); + + // Note that we are done with the test. + done++; +} + +class Sender : public ACE_Handler +{ + // = TITLE + // The class will be created by <main>. +public: + Sender (void); + ~Sender (void); + int open (const char *host, u_short port); + +protected: + // These methods are called by the freamwork + + virtual void handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result); + // This is called when asynchronous writes from the dgram socket + // complete + +private: + + ACE_SOCK_Dgram sockDgram_; + // Network I/O handle + + ACE_Asynch_Write_Dgram wd_; + // wd (write dgram): for writing to the socket + + const char* completion_key_; + const char* act_; +}; + +Sender::Sender (void) + : completion_key_ ("Sender completion key"), + act_ ("Sender ACT") +{ +} + +Sender::~Sender (void) +{ + this->sockDgram_.close (); +} + +int +Sender::open (const char *host, + u_short port) +{ + // Initialize stuff + + if (this->sockDgram_.open(ACE_INET_Addr::sap_any) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_SOCK_Dgram::open"), -1); + + // Initialize the asynchronous read. + if (this->wd_.open (*this, + this->sockDgram_.get_handle (), + this->completion_key_, + ACE_Proactor::instance ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_Asynch_Write_Dgram::open"), -1); + + // We are using scatter/gather to send the message header and + // message body using 2 buffers + + // create a message block for the message header + ACE_Message_Block* msg = 0; + ACE_NEW_RETURN(msg, ACE_Message_Block(100), -1); + const char rawMsg [] = "To be or not to be."; + // Copy buf into the Message_Block and update the wr_ptr (). + msg->copy(rawMsg, ACE_OS::strlen(rawMsg) + 1); + + // create a message block for the message body + ACE_Message_Block* body = 0; + ACE_NEW_RETURN(body, ACE_Message_Block(100), -1); + ACE_OS::memset(body->wr_ptr(), 'X', 100); + body->wr_ptr(100); // always remember to update the wr_ptr() + + // set body as the cont of msg. This associates the 2 message blocks so + // that a send will send the first block (which is the header) up to + // length(), and use the cont() to get the next block to send. You can + // chain up to IOV_MAX message block using this method. + msg->cont(body); + + + // do the asynch send + size_t number_of_bytes_sent = 0; + ACE_INET_Addr serverAddr(port, host); + int res = this->wd_.send(msg, number_of_bytes_sent, 0, serverAddr, this->act_); + + switch (res) + { + case 0: + // this is a good error. The proactor will call our handler when the + // send has completed. + break; + case 1: + // actually sent something, we will handle it in the handler callback + ACE_DEBUG ((LM_DEBUG, "********************\n")); + ACE_DEBUG ((LM_DEBUG, + "%s = %d\n", + "bytes sent immediately", + number_of_bytes_sent)); + ACE_DEBUG ((LM_DEBUG, "********************\n")); + res = 0; + break; + case -1: + // Something else went wrong. + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE_Asynch_Write_Dgram::recv")); + // the handler will not get called in this case so lets clean up our msg + msg->release (); + break; + default: + // Something undocumented really went wrong. + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE_Asynch_Write_Dgram::recv")); + msg->release (); + break; + } + return res; +} + +void +Sender::handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result) +{ + ACE_DEBUG ((LM_DEBUG, + "handle_write_dgram called\n")); + + ACE_DEBUG ((LM_DEBUG, "********************\n")); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ())); + ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "act", result.act ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ())); + ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "completion_key", result.completion_key ())); + ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ())); + ACE_DEBUG ((LM_DEBUG, "********************\n")); + + + ACE_DEBUG ((LM_DEBUG, + "Sender completed\n")); + + // No need for this message block anymore. + result.message_block ()->release (); + + // Note that we are done with the test. + done++; +} + +static int +parse_args (int argc, char *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, "h:p:"); + int c; + + while ((c = get_opt ()) != EOF) + switch (c) + { + case 'h': + host = get_opt.optarg; + break; + case 'p': + port = ACE_OS::atoi (get_opt.optarg); + break; + default: + ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", + "usage :\n" + "-h <host>\n"), -1); + } + + return 0; +} + +int +main (int argc, char *argv[]) +{ + if (parse_args (argc, argv) == -1) + return -1; + + Sender sender; + + Receiver receiver; + + // If passive side + if (host == 0) + { + if (receiver.open (ACE_INET_Addr (port)) == -1) + return -1; + } + // If active side + else if (sender.open (host, port) == -1) + return -1; + + for (int success = 1; + success > 0 && !done; + ) + // Dispatch events via Proactor singleton. + success = ACE_Proactor::instance ()->handle_events (); + + return 0; +} + +#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/ + diff --git a/examples/Reactor/Proactor/test_udp_proactor.dsp b/examples/Reactor/Proactor/test_udp_proactor.dsp new file mode 100644 index 00000000000..ed7d9bf3055 --- /dev/null +++ b/examples/Reactor/Proactor/test_udp_proactor.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="test_udp_proactor" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=test_udp_proactor - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "test_udp_proactor.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "test_udp_proactor.mak" CFG="test_udp_proactor - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "test_udp_proactor - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "test_udp_proactor - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "test_udp_proactor - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "test_udp_proactor - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "test_udp_proactor___Win32_Debug"
+# PROP BASE Intermediate_Dir "test_udp_proactor___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\..\..\ace"
+# SUBTRACT LINK32 /pdbtype:<none>
+
+!ENDIF
+
+# Begin Target
+
+# Name "test_udp_proactor - Win32 Release"
+# Name "test_udp_proactor - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\test_udp_proactor.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
|