cpp-inserver-fancy.cpp

来自「ace开发环境 用来开发网络程序 其运用了设计模式、多平台、C++等多种知识」· C++ 代码 · 共 587 行

CPP
587
字号
 // $Id: CPP-inserver-fancy.cpp 78962 2007-07-20 03:27:14Z sowayaa $// This example tests the features of the <ACE_SOCK_Acceptor>,// <ACE_SOCK_Stream>, and <ACE_Svc_Handler> classes.  If the platform// supports threads it uses a thread-per-connection concurrency model.// Otherwise, it uses a single-threaded iterative server model.#include "ace/OS_main.h"#include "ace/SOCK_Acceptor.h"#include "ace/Svc_Handler.h"#include "ace/Singleton.h"#include "ace/Profile_Timer.h"#include "ace/Get_Opt.h"#include "ace/OS_NS_sys_select.h"#include "CPP-inserver-fancy.h"ACE_RCSID(SOCK_SAP, CPP_inserver_fancy, "$Id: CPP-inserver-fancy.cpp 78962 2007-07-20 03:27:14Z sowayaa $")// Forward declaration.class Handler;class Handler_Factory{  // = TITLE  //   Creates the oneway or twoway handlers.public:  Handler_Factory (void);  // Constructor.  ~Handler_Factory (void);  // Destructor.  int handle_events (void);  // Run the main event loop.private:  int init_acceptors (void);  // Initialize the acceptors.  int create_handler (ACE_SOCK_Acceptor &acceptor,                      Handler *(*handler_factory) (ACE_HANDLE),                      const char *handler_type);  // Factory that creates the right kind of <Handler>.  // = Factory functions.  static Handler *make_twoway_handler (ACE_HANDLE);  // Create a twoway handler.  static Handler *make_oneway_handler (ACE_HANDLE);  // Create a oneway handler.  ACE_SOCK_Acceptor twoway_acceptor_;  // Twoway acceptor factory.  ACE_SOCK_Acceptor oneway_acceptor_;  // Oneway acceptor factory.};class Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>{  // = TITLE  //   Base class for the oneway and twoway handlers.  friend class Handler_Factory;  // The factory has special permission. (to access svc ()).public:  //FUZZ: disable check_for_lack_ACE_OS  virtual int open (void * = 0);  // Generic initialization method.  virtual int close (u_long);  // Close down and delete this.  //FUZZ: enable check_for_lack_ACE_OSprotected:  Handler (ACE_HANDLE handle);  // Constructor.  int parse_header_and_allocate_buffer (char *&buf,                                        ACE_INT32 *len);  // Implement the generic code that's called from any of the subclass  // <run> methods to get the header and the buffer to read the data.  // This method factors out common code.  virtual int run (void) = 0;  // Hook method called by the <svc> template method to do the actual  // protocol.  Must be overridden by the subclass.  virtual int svc (void);  // Template method entry point into the handler task.  virtual void print_results (void);  // Print the results.  size_t total_bytes_;  // Total number of bytes received.  size_t message_count_;  // Number of messages received.  ACE_Profile_Timer timer_;  // Keeps track of how much time we're using.};class Twoway_Handler : public Handler{  // = TITLE  //   Performs the twoway protocol.public:  Twoway_Handler (ACE_HANDLE handle);  // Constructor.private:  virtual int run (void);  // Template Method hook called by <svc>.};class Oneway_Handler : public Handler{  // = TITLEpublic:  Oneway_Handler (ACE_HANDLE handle);  // Constructor.private:  virtual int run (void);  // Template Method hook called by <svc>.  virtual void print_results (void);  // Print the results.};u_shortOptions::port (void) const{  return this->port_;}intOptions::verbose (void) const{  return this->verbose_;}intOptions::reply_message_len (void) const{  return this->reply_message_len_;}Options::~Options (void){}Options::Options (void)  : verbose_ (0),    port_ (ACE_DEFAULT_SERVER_PORT),    reply_message_len_ (24) // Default to the approximate size of an                            // GIOP reply message.{}intOptions::parse_args (int argc, ACE_TCHAR *argv[]){  //FUZZ: disable check_for_lack_ACE_OS  ACE_Get_Opt getopt (argc, argv, ACE_TEXT("p:r:v"), 1);  for (int c; (c = getopt ()) != -1; )  //FUZZ: enable check_for_lack_ACE_OS    switch (c)      {      case 'p':        this->port_ = ACE_OS::atoi (getopt.opt_arg ());        break;      case 'r':        this->reply_message_len_ = ACE_OS::atoi (getopt.opt_arg ());        break;      case 'v':        this->verbose_ = 1;        break;      default:        ACE_ERROR_RETURN ((LM_ERROR,                           "(%P|%t) usage: %n [-p <port>] [-v]"),                          -1);      }  return 0;}// Options Singleton.typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;Handler::Handler (ACE_HANDLE handle)  : total_bytes_ (0),    message_count_ (0){  this->peer ().set_handle (handle);}intHandler::open (void *){  ACE_INET_Addr cli_addr;  // Make sure we're not in non-blocking mode.  if (this->peer ().disable (ACE_NONBLOCK) == -1)    ACE_ERROR_RETURN ((LM_ERROR,                       "%p\n",                       "disable"),                       0);  ACE_DEBUG ((LM_DEBUG,              "(%P|%t) client %s connected from %d on handle %d\n",              cli_addr.get_host_name (),              cli_addr.get_port_number (),              this->peer ().get_handle ()));  return 0;}intHandler::close (u_long){  ACE_DEBUG ((LM_DEBUG,              "(%P|%t) closing down %x\n",              this));  delete this;  return 0;}intHandler::svc (void){  // Timer logic.  this->timer_.start ();  // Invoke the hook method to run the specific test.  int result = this->run ();  this->timer_.stop ();  this->print_results ();  return result;}intHandler::parse_header_and_allocate_buffer (char *&request,                                           ACE_INT32 *len){  ssize_t result = this->peer ().recv_n ((void *) len,                                         sizeof (ACE_INT32));  if (result == 0)    {      ACE_DEBUG ((LM_DEBUG,                  "(%P|%t) connected closed\n"));      return -1;    }  else if (result == -1 || result != sizeof (ACE_INT32))    ACE_ERROR_RETURN ((LM_ERROR,                       "(%P|%t) %p\n",                       "recv_n failed"),                      -1);  else    {      *len = ntohl (*len);      ACE_NEW_RETURN (request,                      char[*len],                      -1);    }  return 0;}voidHandler::print_results (void){}Twoway_Handler::Twoway_Handler (ACE_HANDLE handle)  : Handler (handle){}// Function entry point into the twoway server task.intTwoway_Handler::run (void){  // Read data from client (terminate on error).  char *request = 0;  for (;;)    {      ACE_INT32 len = 0;      if (parse_header_and_allocate_buffer (request,                                            &len) == -1)        return -1;      // Subtract off the sizeof the length prefix.      ssize_t r_bytes = this->peer ().recv_n (request,                                              len - sizeof (ACE_UINT32));      if (r_bytes == -1)        {          ACE_ERROR ((LM_ERROR,                      "%p\n",                      "recv"));          break;        }      else if (r_bytes == 0)        {          ACE_DEBUG ((LM_DEBUG,                      "(%P|%t) reached end of input, connection closed by client\n"));          break;        }      else if (OPTIONS::instance ()->verbose ()               && ACE::write_n (ACE_STDOUT,                                request,                                r_bytes) != r_bytes)        ACE_ERROR ((LM_ERROR,                    "%p\n",                    "ACE::write_n"));      else        {          ssize_t s_bytes = (ssize_t) OPTIONS::instance ()->reply_message_len ();          // Don't try to send more than is in the request buffer!          if (s_bytes > r_bytes)            s_bytes = r_bytes;          if (this->peer ().send_n (request,                                    s_bytes) != s_bytes)            ACE_ERROR ((LM_ERROR,                        "%p\n",                        "send_n"));        }      this->total_bytes_ += size_t (r_bytes);      this->message_count_++;      delete [] request;      request = 0;    }  delete [] request;  return 0;}Oneway_Handler::Oneway_Handler (ACE_HANDLE handle)  : Handler (handle){}voidOneway_Handler::print_results (void){  ACE_Profile_Timer::ACE_Elapsed_Time et;  this->timer_.elapsed_time (et);  ACE_DEBUG ((LM_DEBUG,              ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),              et.real_time,              et.user_time,              et.system_time));  ACE_DEBUG ((LM_DEBUG,              ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n"),              this->message_count_,              this->total_bytes_,              (((double) this->total_bytes_ * 8) / et.real_time) / (double) (1024 * 1024),              ((et.user_time + et.system_time) / (double) this->message_count_) * ACE_ONE_SECOND_IN_USECS));}// Function entry point into the oneway server task.intOneway_Handler::run (void){  // Read data from client (terminate on error).  char *request = 0;  for (;;)    {      ACE_INT32 len = 0;      if (parse_header_and_allocate_buffer (request,                                            &len) == -1)        return -1;      // Subtract off the sizeof the length prefix.      ssize_t r_bytes = this->peer ().recv_n (request,                                              len - sizeof (ACE_UINT32));      if (r_bytes == -1)        {          ACE_ERROR ((LM_ERROR,                      "%p\n",                      "recv"));          break;        }      else if (r_bytes == 0)        {          ACE_DEBUG ((LM_DEBUG,                      "(%P|%t) reached end of input, connection closed by client\n"));          break;        }      else if (OPTIONS::instance ()->verbose ()               && ACE::write_n (ACE_STDOUT,                                request,                                r_bytes) != r_bytes)        ACE_ERROR ((LM_ERROR,                    "%p\n",                    "ACE::write_n"));      this->total_bytes_ += size_t (r_bytes);      this->message_count_++;      delete [] request;      request = 0;    }  delete [] request;  return 0;}// Create a twoway handler.Handler *Handler_Factory::make_twoway_handler (ACE_HANDLE handle){  return new Twoway_Handler (handle);}// Create a oneway handler.Handler *Handler_Factory::make_oneway_handler (ACE_HANDLE handle){  return new Oneway_Handler (handle);}intHandler_Factory::init_acceptors (void){  // Create the oneway and twoway server addresses.  ACE_INET_Addr twoway_server_addr (OPTIONS::instance ()->port ());  ACE_INET_Addr oneway_server_addr (OPTIONS::instance ()->port () + 1);  // Create acceptors, reuse the address.  if (this->twoway_acceptor_.open (twoway_server_addr, 1) == -1      || this->oneway_acceptor_.open (oneway_server_addr, 1) == -1)    ACE_ERROR_RETURN ((LM_ERROR,                       "%p\n",                       "open"),                      -1);  else if (this->twoway_acceptor_.get_local_addr (twoway_server_addr) == -1           || this->oneway_acceptor_.get_local_addr (oneway_server_addr) == -1)    ACE_ERROR_RETURN ((LM_ERROR,                       "%p\n",                       "get_local_addr"),                      -1);  ACE_DEBUG ((LM_DEBUG,              "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",              twoway_server_addr.get_port_number (),              oneway_server_addr.get_port_number ()));  return 0;}intHandler_Factory::create_handler (ACE_SOCK_Acceptor &acceptor,                                 Handler * (*handler_factory) (ACE_HANDLE),                                 const char *handler_type){  ACE_SOCK_Stream new_stream;  if (acceptor.accept (new_stream) == -1)    ACE_ERROR_RETURN ((LM_ERROR,                       "%p\n",                       "accept"),                       -1);  Handler *handler;  ACE_ALLOCATOR_RETURN (handler,                        (*handler_factory) (new_stream.get_handle ()),                        -1);  ACE_DEBUG ((LM_DEBUG,              "(%P|%t) spawning %s handler\n",              handler_type));  if (handler->open () == -1)    return -1;#if defined (ACE_MT_SAFE)  // Spawn a new thread and run the new connection in that thread of  // control using the <server> function as the entry point.  return handler->activate ();#else  handler->svc ();  handler->close (0);  return 0;#endif /* ACE_HAS_THREADS */}Handler_Factory::Handler_Factory (void){}Handler_Factory::~Handler_Factory (void){  this->twoway_acceptor_.close ();  this->oneway_acceptor_.close ();}// Run the main event loop.intHandler_Factory::handle_events (void){  if (this->init_acceptors () == -1)    return -1;  fd_set handles;  FD_ZERO (&handles);  FD_SET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (),          &handles);  FD_SET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (),          &handles);  // Performs the iterative server activities.  for (;;)    {      ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);      fd_set temp = handles;      int result = ACE_OS::select (int (this->oneway_acceptor_.get_handle ()) + 1,                                   (fd_set *) &temp,                                   0,                                   0,                                   timeout);      if (result == -1)        ACE_ERROR ((LM_ERROR,                    "(%P|%t) %p\n",                    "select"));      else if (result == 0 && OPTIONS::instance ()->verbose ())        ACE_DEBUG ((LM_DEBUG,                    "(%P|%t) select timed out\n"));      else        {          if (FD_ISSET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (),                        &temp))            this->create_handler (this->twoway_acceptor_,                                  &Handler_Factory::make_twoway_handler,                                  "twoway");          if (FD_ISSET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (),                        &temp))            this->create_handler (this->oneway_acceptor_,                                  &Handler_Factory::make_oneway_handler,                                  "oneway");        }    }  ACE_NOTREACHED (return 0;)}intACE_TMAIN (int argc, ACE_TCHAR *argv[]){  OPTIONS::instance ()->parse_args (argc, argv);  Handler_Factory server;  return server.handle_events ();}#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)template ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> *  ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX>::singleton_;#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?