// $Id$ // ============================================================================ // // = LIBRARY // tests // // = FILENAME // Conn_Test.cpp // // = DESCRIPTION // This is a test of the and // classes. The test forks processes or spawns threads (depending // upon the platform) and then executes client and server allowing // them to connect and exchange data. The test also illustrates // how the works by showing how you can // cache connections on the client. // // = AUTHOR // Douglas C. Schmidt , // Chris Cleeland , // and Irfan Pyarali // // ============================================================================ #include "test_config.h" #include "ace/SOCK_Connector.h" #include "ace/LOCK_SOCK_Acceptor.h" #include "ace/Acceptor.h" #include "ace/Handle_Set.h" #include "ace/Connector.h" #include "ace/Auto_Ptr.h" #include "ace/Get_Opt.h" #include "ace/Process_Mutex.h" #include "Conn_Test.h" ACE_RCSID(tests, Conn_Test, "$Id$") static const char ACE_ALPHABET[] = "abcdefghijklmnopqrstuvwxyz"; // The following works around bugs with some operating systems, which // don't allow multiple threads/process to call accept() on the same // listen-mode port/socket. Also, note that since timed accept is // implemented using select(), and we use timed accepts with threads, // we need a real lock when using timed accepts even if the OS has // thread-safe accept. // #if defined (ACE_LACKS_FORK) # if defined (ACE_HAS_THREADS) typedef ACE_Thread_Mutex ACCEPTOR_LOCKING; # else typedef ACE_Null_Mutex ACCEPTOR_LOCKING; # endif /* ACE_HAS_THREADS */ #else # if defined (ACE_HAS_THREAD_SAFE_ACCEPT) typedef ACE_Null_Mutex ACCEPTOR_LOCKING; # else typedef ACE_Process_Mutex ACCEPTOR_LOCKING; # endif /* ACE_HAS_THREAD_SAFE_ACCEPT */ #endif /* ACE_LACKS_FORK */ #if defined (ACE_HAS_TEMPLATE_TYPEDEFS) #define LOCK_SOCK_ACCEPTOR ACE_LOCK_SOCK_Acceptor #else #define LOCK_SOCK_ACCEPTOR ACE_LOCK_SOCK_Acceptor, ACE_INET_Addr #endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ typedef ACE_Oneshot_Acceptor ACCEPTOR; typedef ACE_Connector CONNECTOR; typedef ACE_Strategy_Connector STRAT_CONNECTOR; typedef ACE_NOOP_Creation_Strategy NULL_CREATION_STRATEGY; typedef ACE_NOOP_Concurrency_Strategy NULL_ACTIVATION_STRATEGY; typedef ACE_Cached_Connect_Strategy CACHED_CONNECT_STRATEGY; #define CACHED_CONNECT_STRATEGY ACE_Cached_Connect_Strategy #define REFCOUNTED_HASH_RECYCLABLE_ADDR ACE_Refcounted_Hash_Recyclable #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) template class CACHED_CONNECT_STRATEGY; template class REFCOUNTED_HASH_RECYCLABLE_ADDR; template class ACE_NOOP_Creation_Strategy; template class ACE_Concurrency_Strategy; template class ACE_Connect_Strategy; template class ACE_Connector_Base; template class ACE_Connector; template class ACE_Creation_Strategy; template class ACE_Hash_Map_Entry; template class ACE_Hash; template class ACE_Equal_To; template class ACE_Reverse_Lock; template class ACE_Guard >; #if defined (ACE_HAS_THREADS) template class ACE_Hash_Map_Manager; template class ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Iterator; template class ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Bucket_Iterator, ACE_Equal_To, ACE_Null_Mutex>; template class ACE_Hash_Map_Reverse_Iterator; template class ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; #endif /* ACE_HAS_THREADS */ template class ACE_Hash_Map_Manager; template class ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX>; template class ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX>; template class ACE_Hash_Map_Iterator; template class ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX>; template class ACE_Hash_Map_Bucket_Iterator, ACE_Equal_To, ACE_SYNCH_RW_MUTEX>; template class ACE_Hash_Map_Reverse_Iterator; template class ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX>; template class ACE_LOCK_SOCK_Acceptor; template class ACE_Oneshot_Acceptor; template class ACE_NOOP_Concurrency_Strategy; template class ACE_Recycling_Strategy; template class ACE_Strategy_Connector; template class ACE_Svc_Handler; template class ACE_NonBlocking_Connect_Handler; template class ACE_Auto_Basic_Array_Ptr; #if defined (__BORLANDC__) // Borland C++ doesn't link with these instantiations in the ACE library. template class ACE_Double_Linked_List; template class ACE_Unbounded_Queue; template class ACE_Unbounded_Queue; #endif /* defined (__BORLANDC__) */ #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) #pragma instantiate CACHED_CONNECT_STRATEGY #pragma instantiate REFCOUNTED_HASH_RECYCLABLE_ADDR #pragma instantiate ACE_NOOP_Creation_Strategy #pragma instantiate ACE_Concurrency_Strategy #pragma instantiate ACE_Connect_Strategy #pragma instantiate ACE_Connector_Base #pragma instantiate ACE_Connector #pragma instantiate ACE_Creation_Strategy #pragma instantiate ACE_Hash_Map_Entry #pragma instantiate ACE_Hash #pragma instantiate ACE_Equal_To #pragma instantiate ACE_Reverse_Lock #pragma instantiate ACE_Guard > #if defined (ACE_HAS_THREADS) #pragma instantiate ACE_Hash_Map_Manager #pragma instantiate ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Iterator #pragma instantiate ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Bucket_Iterator, ACE_Equal_To, ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Reverse_Iterator #pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> #endif /* ACE_HAS_THREADS */ #pragma instantiate ACE_Hash_Map_Manager #pragma instantiate ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_Hash_Map_Iterator #pragma instantiate ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_Hash_Map_Bucket_Iterator, ACE_Equal_To, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_Hash_Map_Reverse_Iterator #pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_LOCK_SOCK_Acceptor #pragma instantiate ACE_Oneshot_Acceptor #pragma instantiate ACE_NOOP_Concurrency_Strategy #pragma instantiate ACE_Recycling_Strategy #pragma instantiate ACE_Strategy_Connector #pragma instantiate ACE_Svc_Handler #pragma instantiate ACE_NonBlocking_Connect_Handler #pragma instantiate ACE_Auto_Basic_Array_Ptr #if defined (__BORLANDC__) // Borland C++ doesn't link with these instantiations in the ACE library. #pragma instantiate ACE_Double_Linked_List #pragma instantiate ACE_Unbounded_Queue #pragma instantiate ACE_Unbounded_Queue #endif /* defined (__BORLANDC__) */ #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ // Default number of clients/servers. #if defined (ACE_HAS_PHARLAP) // PharLap is, by default, resource contrained. Test for something that works // on the default configuration. static int n_servers = 2; static int n_clients = 4; #else static int n_servers = 5; static int n_clients = 5; #endif /* ACE_HAS_PHARLAP */ static int n_client_iterations = 3; Svc_Handler::Svc_Handler (ACE_Thread_Manager *) { } int Svc_Handler::open (void *) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) opening Svc_Handler %@ with handle %d\n"), this, this->peer ().get_handle ())); // Enable non-blocking I/O. if (this->peer ().enable (ACE_NONBLOCK) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")), -1); return 0; } int Svc_Handler::recycle (void *) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) recycling Svc_Handler %@ with handle %d\n"), this, this->peer ().get_handle ())); return 0; } void Svc_Handler::send_data (void) { // Send data to server. for (const char *c = ACE_ALPHABET; *c != '\0'; c++) if (this->peer ().send_n (c, 1) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n"))); } void Svc_Handler::recv_data (void) { ACE_SOCK_Stream &new_stream = this->peer (); ACE_Handle_Set handle_set; handle_set.set_bit (new_stream.get_handle ()); const char *t = ACE_ALPHABET; // Read data from client (terminate on error). for (ssize_t r_bytes; ;) { // Since we're in non-blocking mode we need to use