sample/high_traffic/server.cpp

/*
  Тестирование поведения коммуникационных агентов при
  большом трафике.

  Серверная часть.

  Так же демонстрирует создание дополнительного TP-реактора
  и использование этого реактора совместно с серверным сокетом.
*/

#include <iostream>

#include <stdio.h>

#include <ace/OS_main.h>

#include <so_4/api/h/api.hpp>
#include <so_4/rt/h/rt.hpp>

#include <so_4/rt/comm/h/a_sop_incoming_channel_processor.hpp>
#include <so_4/transport_layer/socket/h/pub.hpp>
#include <so_4/ace/h/reactors.hpp>

#include <so_4/timer_thread/simple/h/pub.hpp>
#include <so_4/disp/one_thread/h/pub.hpp>

#include "common.cpp"

// Класс тестового агента, который получает сообщения.
class a_receiver_t
  : public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;
  public :
    a_receiver_t()
    :
      base_type_t( "a_receiver" )
    {}
    virtual ~a_receiver_t()
    {}

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription()
    {
      // Агент a_common должен быть глобальным.
      so_4::api::make_global_agent(
        a_common_t::agent_name(),
        a_common_t::agent_type() );

      so_subscribe( "evt_request",
        a_common_t::agent_name(),
        "msg_request" );

      so_subscribe( "evt_client_connected",
        "a_channel", "msg_client_connected" );

      so_subscribe( "evt_client_disconnected",
        "a_channel", "msg_client_disconnected" );
    }

    void
    evt_request(
      const so_4::rt::event_data_t & data,
      const a_common_t::msg_request * cmd )
    {
      std::cout << cmd->m_uid << " ";
      // Сразу отвечаем ответным сообщением.
      so_4::api::send_msg_safely(
        data.channel(),
        a_common_t::agent_name(),
        "msg_reply",
        new a_common_t::msg_reply( cmd->m_uid ) );
    }

    void
    evt_client_connected(
      const so_4::rt::event_data_t & data,
      const so_4::rt::comm::msg_client_connected * cmd )
    {
      std::cout << "\nclient connected: " << cmd->m_channel
        << std::endl;
    }

    void
    evt_client_disconnected(
      const so_4::rt::event_data_t & data,
      const so_4::rt::comm::msg_client_disconnected * cmd )
    {
      std::cout << "\nclient disconnected: " << cmd->m_channel
        << std::endl;
    }
};

SOL4_CLASS_START( a_receiver_t )

  SOL4_EVENT_STC(
    evt_request,
    a_common_t::msg_request )
  SOL4_EVENT_STC(
    evt_client_connected,
    so_4::rt::comm::msg_client_connected )
  SOL4_EVENT_STC(
    evt_client_disconnected,
    so_4::rt::comm::msg_client_disconnected )

  SOL4_STATE_START( st_normal )
    SOL4_STATE_EVENT( evt_request )
    SOL4_STATE_EVENT( evt_client_connected )
    SOL4_STATE_EVENT( evt_client_disconnected )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

int
main( int argc, char ** argv )
{
  if( 2 == argc )
  {
    // Создаем TP-реактор, который будет использоваться
    // серверным сокетом.
    so_4::ace::reactor_registry().add(
        "a_channel_reactor",
        // ТР-реактор будет работать на четырех нитях.
        so_4::ace::make_tp_reactor( 4 ) );

    // Создаем канал и указываем, какой реактор для него будет
    // использован.
    so_4::rt::comm::a_sop_incoming_channel_processor_t a_channel(
      "a_channel",
      // Для задания реактора нужно использовать функцию
      // create_acceptor_controller со всеми параметрами.
      so_4::transport_layer::socket::create_acceptor_controller(
          so_4::transport_layer::socket::acceptor_params( argv[ 1 ] ),
          so_4::transport_layer::channel_params_t(),
          so_4::transport_layer::socket::option_setter_auto_ptr_t(),
          // Вот и реактор, на котором предстоит работать каналу.
          so_4::ace::reactor_registry().find( "a_channel_reactor" ) ) );

    a_receiver_t a_receiver;

    so_4::rt::agent_t * agents[] =
    {
      &a_channel, &a_receiver
    };
    so_4::rt::agent_coop_t coop( "server",
      agents, sizeof( agents ) / sizeof( agents[ 0 ] ) );

    so_4::ret_code_t rc = so_4::api::start(
      // Диспетчер будет уничтожен при выходе из start().
      so_4::disp::one_thread::create_disp(
        // Таймер будет уничтожен диспетчером.
        so_4::timer_thread::simple::create_timer_thread(),
        so_4::auto_destroy_timer ),
      so_4::auto_destroy_disp,
      &coop );

    if( rc )
    {
      std::cerr << "start: " << rc << std::endl;
    }

    return int( rc );
  }

  std::cerr << "sample_high_traffic_server <[ip]:port>" << std::endl;
  return 1;
}

Документация по SObjectizer v.4.4 'Тебуломста'. Последние изменения: Thu Sep 18 10:26:45 2008. Создано системой  doxygen1.5.6 Intervale SourceForge.net Logo