comp.lang.ada
 help / color / mirror / Atom feed
From: anon@anon.org (anon)
Subject: Re: Structure of the multitasking server
Date: Tue, 23 Sep 2008 09:25:41 GMT
Date: 2008-09-23T09:25:41+00:00	[thread overview]
Message-ID: <pC2Ck.48289$Mh5.6543@bgtnsc04-news.ops.worldnet.att.net> (raw)
In-Reply-To: 34752018-8305-42f2-ac98-2c3a0e8e482d@25g2000hsx.googlegroups.com

--
--  A Server and a Client that shows how to use 
--  GNAT.Sockets.Check_Selection as a controller for
--  multiple port server. And can be alter to allow multiple 
--  services type of server.
--
--  In C,  they call this type of server a Super-Server Class 
--  of servers.
--

-- ------------------------------------------------------------ --
-- Multi-Tasking Server that allows Multi-Service to be handled --
-- ------------------------------------------------------------ --

with Ada.Text_IO ;
with GNAT.Sockets ;
with System ;

use  Ada.Text_IO ;
use  GNAT.Sockets ;

procedure testserver is 


  -- ------------------- --
  --  Server Task Types  --
  -- ------------------- --

    -- 
    --  TCP Task
    -- 

    task tcp_hello is
        entry Initialize ;
        entry Acknowledge ;
      end tcp_hello ;


    -- 
    --  UDP Task
    -- 

    task udp_hello is
        entry Initialize ;
        entry Acknowledge ;
      end udp_hello ;


    Server_Error  : exception ;

    tcp_Socket    : Socket_Type       ;
    udp_Socket    : Socket_Type       ;


-- ------------------------------------------------------------------------ --
----                        TCP/IP Controller Task                        ----
----                                                                      ----
----  dispatches server task to handle tcp/ip services.                   ----
----                                                                      ----
-- ------------------------------------------------------------------------ --

    task Controller is
        entry Initialize_Controller ;
      end Controller  ;


    task body Controller is

        Selector      : Selector_Type   ;
        Server_Status : Selector_Status ;

        --  Exception_Fds is not use in Ada 95
        --  and is optional Ada 2005 GNAT.Sockets

        Read_Fds      : Socket_Set_Type ;
        Write_Fds     : Socket_Set_Type ;


      begin -- Controller 
          --
          -- Set up controller variables
          --
          Create_Selector ( Selector ) ;
          Empty ( Read_Fds ) ;
          Empty ( Write_Fds ) ;


          Accept Initialize_Controller ;

          --
          -- Set up and active Server
          --
          Put_Line ( "Controller: Server Dispatching Loop" ) ;
          loop
            -- Insure Fds value, 
            Empty ( Read_Fds ) ;
            Empty ( Write_Fds ) ;

            Set ( Read_Fds, tcp_Socket ) ;
            Set ( Read_Fds, udp_Socket ) ;

            --
            --  Excute the TCP/IP "Select" routine.  This routine is blocked
            --  until a connecion is made. In this part it is identical to 
            --  TCP/IP "Accept".
            --
            --  Also, Exception_Fds is not use in Ada 95 and is optional 
            --  Ada 2005 GNAT.Sockets
            --
            Check_Selector ( Selector, 
                             Read_Fds, 
                             Write_Fds, 
                             Server_Status ) ;

            -- call a server to handle job using Signalling Fds

            if Is_Set ( Read_Fds, tcp_Socket ) then
                tcp_hello.Acknowledge ;
            elsif Is_Set ( Read_Fds, udp_Socket ) then
                udp_hello.Acknowledge ;
            else
              raise Socket_Error ;
            end if ;
          end loop ;
       exception
         when Socket_Error => 
             -- need to signal servers to shutdown because 
             -- dispatcher has stopped
             raise ;            
      end Controller  ;




-- ------------------------------------------------------------------------ --
----                         TCP/IP Server Tasks                          ----
----                                                                      ----
----  Both tasks are similar.  They both send a message to a client       ----
----  Differences:                                                        ----
----        1) Transport protocols: One uses TCP, the other uses UDP      ----
----        2) Message and message length                                 ----
----                                                                      ----
----  Excution of these two servers will cause the "netstat" program      ----
----  to add the following info to the "netstat" socket report            ----
----                                                                      ----
----      IP Address        protocol    port                              ----
----      127.0.0.1         tcp         54321                             ----
----      127.0.0.1         udp         54321                             ----
----                                                                      ----
-- ------------------------------------------------------------------------ --



    task body tcp_hello is

        Port         : constant Port_Type := 54321 ;

        Address      : Sock_Addr_Type    ;
        Channel      : Stream_Access     ;
        Client       : Socket_Type       ; 

        hello_string : String ( 1..25 ) := "TCP Server: Hello, World!" ; 

      begin -- Tcp_hello

        Create_Socket ( tcp_Socket, Family_Inet, Socket_Stream ) ;
        --
--        Address.Addr := Any_Inet_Addr ;
        Address.Addr := Inet_Addr ( "127.0.0.1" ) ; -- Limited access
        Address.Port := Port ;
        --
        Bind_Socket ( tcp_Socket, Address ) ;

        --
        Listen_Socket ( tcp_Socket, 4 ) ;  

        Accept Initialize ;
        --
        --  Main Server processing routine 
        --
        Put_Line ( "TCP: Active the Server loop" ) ;
        loop 
          accept Acknowledge ;

          -- ------------------------ --
          --  Do server services job  --
          -- ------------------------ --

          --
          --  Because of Check_Selector, no wait for Accept_Socket
          --  used to obtain connected socket ( Client ) address 
          --  for the tcp protocol.
          --
          Accept_Socket ( tcp_Socket, Client, Address ) ;

          Channel := Stream ( Client ) ;

          String'Write ( Channel, hello_string ) ;

          Close_Socket ( Client ) ;

        end loop ;

        --
        -- for security, close socket if exception occured
        --
        exception
          when others =>
              Put_Line ( "TCP: Exception" ) ;
              Close_Socket ( tcp_Socket ) ;
              raise ;
      end tcp_hello ;



    -- 
    --  UDP Task
    -- 

    task body udp_hello is

        Port           : constant Port_Type := 54321 ;

        Address        : Sock_Addr_Type    ;
        Channel_Input  : Stream_Access     ;
        Channel_Output : Stream_Access     ;

        Temp           : Character         ;
        hello_string : String := "UDP Server: Repeat Hello, World!" ; 

      begin -- udp_hello

        Create_Socket ( udp_Socket, Family_Inet, Socket_Datagram ) ;
        --
--        Address.Addr := Any_Inet_Addr ;
        Address.Addr := Inet_Addr ( "127.0.0.1" ) ;
        Address.Port := Port ;
        --
        Bind_Socket ( udp_Socket, Address ) ;


        Accept Initialize ;
        --
        --  Main Server processing routine 
        --
        Put_Line ( "UDP: Active the Server loop" ) ;
        loop 
          accept Acknowledge ;

          -- ------------------------ --
          --  Do server services job  --
          -- ------------------------ --
                                           -- Accept from any Address and Port
          Address.Addr := Any_Inet_Addr ;
          Address.Port := Any_Port ;

          Channel_Input := Stream ( udp_Socket, Address ) ;  
      
          Character'Read ( Channel_Input, Temp ) ;

                                           -- Open an output channel
          Address := Get_Address ( Channel_Input ) ;
          Channel_Output := Stream ( udp_Socket, Address ) ;

          String'Write ( Channel_Output, hello_string ) ;
        end loop ;

        --
        -- for security, close socket if exception occured
        --
        exception
          when others =>
              Put_Line ( "UDP: Exception" ) ;
              Close_Socket ( udp_Socket ) ;
              raise ;
      end udp_hello ;



                      -- ------------------------ --
                      ----   Server Initiaizer  ----
                      -- ------------------------ --



  begin

    -- Initialize each server service task

    tcp_hello.Initialize ;
    udp_hello.Initialize ;

    --  Startup network controller

    Controller.Initialize_Controller ;

  --
  -- Handle all exceptions
  --
  exception 
    when Socket_Error =>
      raise ;
    when others =>
      raise ;
  end testserver ;





-- ----------------------------------------------------- --
-- Non-Tasking Client that test the Multi-Service Server --
-- ----------------------------------------------------- --

with Ada.Command_Line ;
with Ada.Text_IO ;
with Ada.Unchecked_Conversion ;
with GNAT.Sockets ;

use  Ada.Command_Line ;
use  Ada.Text_IO ;
use  GNAT.Sockets ;

procedure testclient is 

    localhost : constant Inet_Addr_Type := Inet_Addr ( "127.0.0.1" ) ;
    localport : constant Port_Type := 54321 ;
    --
    Address : Sock_Addr_Type    ;
    Channel : Stream_Access     ;
    Socket  : Socket_Type       ;
    --
    tcp_Buffer  : String ( 1..25 )  ;
    udp_Buffer  : String ( 1..32 )  ;

  begin -- Daytime0

    --
    Address.Addr := localhost ;
    Address.Port := localport ;

    --
    if Argument ( 1 ) = "-T" then
      Put_Line ( "Protocol: TCP" ) ;
      --
      Create_Socket ( Socket, Family_Inet, Socket_Stream ) ;
      Connect_Socket ( Socket, Address ) ;
      --
      Channel := Stream ( Socket ) ;
      String'Read ( Channel, tcp_Buffer ) ;
      --
      Close_Socket ( Socket ) ;
      --
      Put ( "Server Data => " ) ;
      Put ( tcp_Buffer ) ;
      Put ( " <= " ) ;
      New_Line ;

    elsif Argument ( 1 ) = "-U" then
      Put_Line ( "Protocol: UDP" ) ;
      --
      Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
      Channel := Stream ( Socket, Address ) ;

      -- Allows server to obtain client address by send a dummy character 

      Character'Write ( Channel, Ascii.nul ) ; 
      --
      Channel := Stream ( Socket, Address ) ;
      String'Read ( Channel, udp_Buffer ) ;
      --
      Close_Socket ( Socket ) ;
      --
      Put ( "Server Data => " ) ;
      Put ( udp_Buffer ) ;
      Put ( " <= " ) ;
      New_Line ;

     else
      Put_Line ( Standard_Error, "usage: testclient [-DT]" ) ;
      Put_Line ( Standard_Error, "-T: tcp" ) ;
      Put_Line ( Standard_Error, "-U: udp" ) ;
      New_Line ;
    end if ;
  end testclient ;



      reply	other threads:[~2008-09-23  9:25 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-19 12:21 Structure of the multitasking server Maciej Sobczak
2008-09-19 13:34 ` Jean-Pierre Rosen
2008-09-19 17:02   ` Dmitry A. Kazakov
2008-09-21 17:30     ` Maciej Sobczak
2008-09-21 19:24       ` Dmitry A. Kazakov
2008-09-21 21:27         ` Maciej Sobczak
2008-09-22  8:12           ` Dmitry A. Kazakov
2008-09-22 12:47             ` Maciej Sobczak
2008-09-22 14:11               ` Dmitry A. Kazakov
2008-09-23  8:07                 ` Maciej Sobczak
2008-09-23  9:37                   ` Dmitry A. Kazakov
2008-09-23 10:47                   ` Jean-Pierre Rosen
2008-09-21 17:23   ` Maciej Sobczak
2008-09-22  8:23     ` Jean-Pierre Rosen
2015-03-12 16:07   ` gautier_niouzes
2015-03-12 21:38     ` Jacob Sparre Andersen
2015-03-12 22:39       ` gautier_niouzes
2015-03-13  8:15         ` Dmitry A. Kazakov
2015-03-13 20:16           ` gautier_niouzes
2015-03-13 20:47             ` Dmitry A. Kazakov
2015-03-15  7:43               ` gautier_niouzes
2015-03-15  8:35                 ` Simon Wright
2015-03-15  8:52                 ` J-P. Rosen
2015-03-15  9:21                   ` Jacob Sparre Andersen
2015-03-15 16:04                     ` Brad Moore
2015-03-13 23:04             ` Randy Brukardt
2015-03-14  8:22               ` Simon Wright
2008-09-19 23:01 ` anon
2008-09-21 17:37   ` Maciej Sobczak
2008-09-22  2:32     ` anon
2008-09-22 13:05       ` Maciej Sobczak
2008-09-23  9:25         ` anon [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox