comp.lang.ada
 help / color / mirror / Atom feed
From: anon@att.net
Subject: Re: Sockets Example Sought
Date: Wed, 28 Nov 2012 04:43:47 +0000 (UTC)
Date: 2012-11-28T04:43:47+00:00	[thread overview]
Message-ID: <k944q2$qig$1@speranza.aioe.org> (raw)
In-Reply-To: 2012112311175432190-rblove@airmailnet

-- 
--  TCP/IP Echo Service Daemon, based on RFC 342 and RFC 862
--  Normally, a Sender program that accepts a word or quoted
--  sentence from command line is transmitted to the server and
--  the return message is displayed.
-- 
--  This Daemon was tested using "Ada Dual TCP/IP Stacks" using
--  IPv6 and Linux IPv4,
-- 
-- 
--  Protocol: TCP
--  Protocol: UDP not setup at this time.
-- 
--  Usage:    Listener
-- 
--  Tester:   Telnet <hostname>  -port 7
--  Example:  Telnet 127.0.0.1 7
-- 
--  While telnet operational every character including control
--  characters will be echoed
-- 

with Ada.Characters.Latin_9 ;
with Ada.Exceptions ;
with Ada.Text_IO ;
with GNAT.Sockets ;   -- GNAT to reg OS
-- with Sockets ;     -- Ada TCP/IP Stacks

use Ada.Characters.Latin_9 ;
use Ada.Exceptions ;
use Ada.Text_IO ;
use GNAT.Sockets ;
-- use Sockets ;     -- Ada TCP/IP Stacks

procedure Listener is

  --
  --  Operational options
  --
  --  Set to True to use IPv6, But some GNAT.Socket packages, are
  --  not setup to handle IPv6 yet. One way to check is to look at
  --  the body for the "Bind" function. Because the "Bind" function
  --  raises a exception, if IPv6 is use, for those packages that
  --  are IPv4 only.
  --
  IP_V6   : constant Boolean := False ;
  --
  -- Displays a logging message if True
  --
  LOGGING : constant Boolean := False ;

  task type Echo is
    entry Start ( Incoming : Socket_Type ) ;
  end Echo ;

  type Echo_Access is access Echo ;
  type Sock_Addr_Access is access all Sock_Addr_Type ;

  --
  -- Echo -- the main processthat preforms the echo operation
  --      -- one problem is there is no recovery of memory use
  --         by this task once the task ends.
  --

  task body Echo is
      Data     : Character     ;

      Channel  : Stream_Access ;
      Socket   : Socket_Type   ;

    begin
      accept Start ( Incoming : Socket_Type ) do
          Socket := Incoming ;
      end Start ;

      Channel := Stream ( Socket ) ;
      loop
        Data := Character ' Input ( Channel ) ;
        exit when Data = ASCII.Nul ;
        Character ' Output ( Channel, Data ) ;
      end loop ;
      Close_Socket ( Socket ) ;
    exception
      when Socket_Error =>
          Put_Line ( "Connection closed" ) ;
          Close_Socket ( Socket ) ;
    end Echo ;

  --
  Accepting_Socket : Socket_Type ;
  Incoming_Socket  : Socket_Type ;
  Address          : Sock_Addr_Access ;

  Dummy            : Echo_Access ;

  TCP_Error        : exception ;

begin
  --  
  --  Create Socket and sets stacks. With error checking to insure
  --  stacks is valid because some system only have IPv4 and other
  --  have remove IPv4. If both stacks are installed and GNAT
  --  allows both, then use IPv6.
  --
  if IP_V6 then
    begin
      --
      -- set IPv6
      --
      Create_Socket ( Accepting_Socket, Family_Inet6, Socket_Stream ) ;
      Address := new Sock_Addr_Type ( Family_Inet6 );
    exception
      when Socket_Error =>
        Put_Line ( "Error: IP version 6 is not supported" ) ;
        raise TCP_Error ;
    end ;
  else
    begin
      --
      -- set Default IPv4
      --
      Create_Socket ( Accepting_Socket ) ;
      Address := new Sock_Addr_Type ;
    exception
      when Socket_Error =>
        Put_Line ( "Error: IP version 4 is not supported" ) ;
        raise TCP_Error ;
    end ;
  end if ;
  --
  --  Address.Addr is current host can be localhost
  --  Address.Port is 7 based on RFC 342 update RFC 862
  --
  Address.all.Addr := Addresses ( Get_Host_By_Name ( Host_Name ), 1 ) ;
  Address.all.Port := 7 ;
  --
  --  Bind Address to socket
  --
  Bind_Socket ( Accepting_Socket, Address.all ) ;
  --
  --  Set stacks to receive connect events
  --
  Listen_Socket ( Accepting_Socket ) ;
  --
  --  Handle connections
  --
  loop
    --
    --  Wait until client request connect then accept connection
    --
    Accept_Socket ( Accepting_Socket,
                    Incoming_Socket, Address.all ) ;
    --
    --  Log message, if required
    --
    if LOGGING then
      Put ( "Received From: " ) ;
      Put ( Image ( Address.all ) ) ;
    end if ;
    --
    --  Create a single usage task to handle daemon process
    --  task will die once connection is ended.  In this design
    --  there is a possible memory leak because once the task
    --  dies there is no memory recover of the dead task.
    --
    Dummy := new Echo ;
    Dummy.Start ( Incoming_Socket ) ;
  end loop ;

exception
  when TCP_Error =>
      Put_Line ( "Error: Server was not initialized" ) ;

  when others =>
      Put_Line ( "Error: Server is beening shutdown" ) ;
      Shutdown_Socket ( Accepting_Socket, Shut_Read_Write ) ;
end Listener ; 

In <2012112311175432190-rblove@airmailnet>, Robert Love <rblove@airmail.net> writes:
>Does anyone have an example of a multi-client server in Ada they care 
>to share?  It should use the Gnat.Sockets package.  I've seen samples 
>but they don't seem complete, or at least my understanding isn't 
>complete<grin>.
>
>Thanks in advance.
>
>




  parent reply	other threads:[~2012-11-28  4:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-23 17:17 Sockets Example Sought Robert Love
2012-11-23 18:32 ` Simon Wright
2012-11-23 21:58   ` Robert Love
2012-11-23 22:40     ` Dmitry A. Kazakov
2012-11-24 18:27       ` Robert Love
2012-11-24 21:01         ` Dmitry A. Kazakov
2012-11-27  3:37           ` Robert Love
2012-11-27  8:41             ` Dmitry A. Kazakov
2012-11-27 15:05             ` Mark Lorenzen
2012-11-23 23:08     ` Simon Wright
2012-11-28  4:43 ` anon [this message]
2012-11-30  5:04   ` Robert Love
replies disabled

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