/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// This example is from the ACE Programmers Guide.
//// Chapter: "The Acceptor/Connector" (Connection Initialization)
//// For details please see the guide at
//// http://www.cs.wustl.edu/~schmidt/ACE.html
//// AUTHOR: Umar Syyid (usyyid@hns.com)
//// and Ambreen Ilyas (ambreen@bitsmart.com)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Example 9
#include "ace/Reactor.h"
#include "ace/Svc_Handler.h"
#include "ace/Connector.h"
#include "ace/Synch.h"
#include "ace/SOCK_Connector.h"
#include "ace/INET_Addr.h"

#define PORT_NUM 10101
#define DATA_SIZE 16

//forward declaration
class My_Svc_Handler;
//Function prototype
static void make_connections(void *arg);

// Template specializations for the hashing function for the
// hash_map which is used by the cache. The cache is used internally by the
// Cached Connection Strategy . Here we use ACE_Hash_Addr
// as our external identifier. This utility class has already
// overloaded the == operator and the hash() method. (The
// hashing function). The hash() method delgates the work to
// hash_i() and we use the IP address and port to get a
// a unique integer hash value.
size_t
ACE_Hash_Addr<ACE_INET_Addr>::hash_i (const ACE_INET_Addr &addr) const
{
return addr.get_ip_address () + addr.get_port_number ();
}

//instantiate a strategy acceptor
typedef ACE_Strategy_Connector<My_Svc_Handler,ACE_SOCK_CONNECTOR>
STRATEGY_CONNECTOR;

//Instantiate the Creation Strategy
typedef ACE_NOOP_Creation_Strategy<My_Svc_Handler>
NULL_CREATION_STRATEGY;
//Instantiate the Concurrency Strategy
typedef ACE_NOOP_Concurrency_Strategy<My_Svc_Handler>
NULL_CONCURRENCY_STRATEGY;
//Instantiate the Connection Strategy
typedef ACE_Cached_Connect_Strategy<My_Svc_Handler,
ACE_SOCK_CONNECTOR,
ACE_SYNCH_RW_MUTEX>
CACHED_CONNECT_STRATEGY;
class My_Svc_Handler:
public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_MT_SYNCH>{
private:
char* data;

public:
My_Svc_Handler(){
data= new char[DATA_SIZE];
}
My_Svc_Handler(ACE_Thread_Manager* tm){
data= new char[DATA_SIZE];
}
//Called before the service handler is recycled..
int
recycle (void *a=0){
ACE_DEBUG ((LM_DEBUG,
"(%P|%t) recycling Svc_Handler %d with handle %d\n",
this, this->peer ().get_handle ()));
return 0;
}

int open(void*){
ACE_DEBUG((LM_DEBUG,"(%t)Connection established \n"));

//Register the service handler with the reactor
ACE_Reactor::instance() ->register_handler(this,ACE_Event_Handler::READ_MASK);
activate(THR_NEW_LWP|THR_DETACHED);
return 0;
}

int handle_input(ACE_HANDLE){
ACE_DEBUG((LM_DEBUG,"Got input in thread: (%t) \n"));
peer().recv_n(data,DATA_SIZE);
ACE_DEBUG((LM_DEBUG,"<< %s\n",data));

//keep yourself registered with the reactor
return 0;
}

int svc(void){
//send a few messages and then mark connection as idle so that it can be recycled later.
ACE_DEBUG((LM_DEBUG,"Started the service routine \n"));

for(int i=0;i<3;i++){
ACE_DEBUG((LM_DEBUG,"(%t)>>Hello World\n"));
ACE_OS::fflush(stdout);
peer().send_n("Hello World",sizeof("Hello World"));
}

//Mark the service handler as being idle now and let the other threads reuse this connection
this->idle(1);

//Wait for the thread to die
this->thr_mgr()->wait();
return 0;
}
};
ACE_INET_Addr *addr;

int main(int argc, char* argv[]){
addr= new ACE_INET_Addr(PORT_NUM,argv[1]);
//Creation Strategy
NULL_CREATION_STRATEGY creation_strategy;

//Concurrency Strategy
NULL_CONCURRENCY_STRATEGY concurrency_strategy;

//Connection Strategy
CACHED_CONNECT_STRATEGY caching_connect_strategy;

//instantiate the connector
STRATEGY_CONNECTOR connector(
ACE_Reactor::instance(), //the reactor to use
&creation_strategy,
&caching_connect_strategy,
&concurrency_strategy);
//Use the thread manager to spawn a single thread to
//connect multiple times passing it the address
//of the strategy connector
if(ACE_Thread_Manager::instance()->spawn(
(ACE_THR_FUNC) make_connections,
(void *) &connector,
THR_NEW_LWP) == -1)
ACE_ERROR ((LM_ERROR, "(%P|%t) %p\n%a", "client thread spawn failed"));

while(1) /* Start the reactor?s event loop */
ACE_Reactor::instance()->handle_events();
}

//Connection establishment function, tries to establish connections
//to the same server again and re-uses the connections from the
//cache
void make_connections(void *arg){
ACE_DEBUG((LM_DEBUG,"(%t)Prepared to connect \n"));
STRATEGY_CONNECTOR *connector= (STRATEGY_CONNECTOR*) arg;
for (int i = 0; i < 10; i++){
My_Svc_Handler *svc_handler = 0;

// Perform a blocking connect to the server using the Strategy
// Connector with a connection caching strategy. Since we are
// connecting to the same <server_addr> these calls will return the
// same dynamically allocated <Svc_Handler> for each <connect> call.
if (connector->connect (svc_handler, *addr) == -1){
ACE_ERROR ((LM_ERROR, "(%P|%t) %p\n", "connection failed\n"));
return;
}

// Rest for a few seconds so that the connection has been freed up
ACE_OS::sleep (5);
}
}
Next Example