comp.lang.ada
 help / color / mirror / Atom feed
From: anon@att.net
Subject: Re: Help writing first daemon  Heres a Server
Date: Sun, 9 Sep 2012 07:26:49 +0000 (UTC)
Date: 2012-09-09T07:26:49+00:00	[thread overview]
Message-ID: <k2hgbn$5d3$1@speranza.aioe.org> (raw)
In-Reply-To: 3b3a796d-50e0-4304-9f8d-295fb2ed0e82@googlegroups.com

--
--  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 <3b3a796d-50e0-4304-9f8d-295fb2ed0e82@googlegroups.com>, Patrick <patrick@spellingbeewinnars.org> writes:
>
>Hi Everyone
>
>I am setting out to write my first daemon. There seems to be a lot of optio=
>ns for inter-process communication on posix systems. I am planning on desig=
>ning a scientific instrument control server that will control ports, like t=
>he serial port, based on signals it is sent. It will also collect data from=
> instruments and store the data(I was thinking in a postgresql database).
>
>I just need signals passed on one machine so yaml4 seems like overkill. I w=
>as thinking that I could write many little commands, with each command spec=
>ific to an instrument it is designed to control and the daemon as more gene=
>ral infrastructure(basically middleware), so it wouldn't really be a parent=
>/child relationship. I'm guessing plain old pipes are out.
>
>Does FIFO/names pipes sound reasonable for this sort of thing? I am concern=
>ed that with many commands acting on the daemon there will be too much over=
>head with these commands creating file handlers.
>
>I am also going to control instruments over Ethernet anyways so would inves=
>ting time in socket programming solve two problems by making it a socket ba=
>sed server? Once the socket is set up by the daemon, the smaller "satellite=
>" commands would not need as much overhead to connect to a port as they wou=
>ld to create a file handler, would they?
>
>Lastly, this will be done in Ada where ever possible, is there an Ada orien=
>ted way to do this sort of thing?
>
>Thanks for reading-Patrick




  parent reply	other threads:[~2012-09-14 17:42 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-07 22:05 Help writing first daemon Patrick
2012-09-08  8:06 ` Dmitry A. Kazakov
2012-09-11 14:38   ` Maciej Sobczak
2012-09-11 15:13     ` Dmitry A. Kazakov
2012-09-11 20:50       ` Maciej Sobczak
2012-09-12  7:16         ` Dmitry A. Kazakov
2012-09-08  8:08 ` björn lundin
2012-09-08 11:22 ` Patrick
2012-09-09  7:26 ` anon [this message]
2012-09-09 12:26 ` Patrick
2012-09-11 14:18 ` Julian Leyh
replies disabled

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