Skip to content

Instantly share code, notes, and snippets.

@msiedlarek
Created August 21, 2012 07:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msiedlarek/3413017 to your computer and use it in GitHub Desktop.
Save msiedlarek/3413017 to your computer and use it in GitHub Desktop.
Socket server terminating on interrupt in Ada
with Ada.Interrupts;
with Ada.Interrupts.Names;
with Servers;
package body Application is
pragma Interrupt_State (
Name => Ada.Interrupts.Names.SIGINT,
State => USER
);
Server : Servers.Server;
protected Interrupt_Handler is
procedure Handle
with Interrupt_Handler;
end Interrupt_Handler;
procedure Run
is
begin
Ada.Interrupts.Attach_Handler (
Interrupt_Handler.Handle'Access,
Ada.Interrupts.Names.SIGINT
);
Servers.Start (Server);
end Run;
protected body Interrupt_Handler is
procedure Handle is begin
Servers.Stop (Server);
end Handle;
end Interrupt_Handler;
end Application;
package Application is
procedure Run;
end Application;
with Application;
procedure Main
is
begin
Application.Run;
end Main;
with Ada.Text_IO;
package body Servers is
procedure Start
(S : in out Server)
is
use type GNAT.Sockets.Selector_Status;
Listener_Socket : GNAT.Sockets.Socket_Type;
Listener_Address : constant GNAT.Sockets.Sock_Addr_Type := (
Family => GNAT.Sockets.Family_Inet,
Addr => GNAT.Sockets.Inet_Addr ("127.0.0.1"),
Port => 4000
);
Client_Socket : GNAT.Sockets.Socket_Type;
Client_Address : GNAT.Sockets.Sock_Addr_Type;
Selector_Status : GNAT.Sockets.Selector_Status;
begin
GNAT.Sockets.Create_Socket (Listener_Socket);
GNAT.Sockets.Set_Socket_Option (
Socket => Listener_Socket,
Level => GNAT.Sockets.Socket_Level,
Option => (
Name => GNAT.Sockets.Reuse_Address,
Enabled => True
)
);
GNAT.Sockets.Bind_Socket (
Socket => Listener_Socket,
Address => Listener_Address
);
GNAT.Sockets.Listen_Socket (Listener_Socket);
Ada.Text_IO.Put_Line (
"Listening on " & GNAT.Sockets.Image (Listener_Address)
);
loop
GNAT.Sockets.Accept_Socket (
Server => Listener_Socket,
Socket => Client_Socket,
Address => Client_Address,
Timeout => GNAT.Sockets.Forever,
Selector => S.Accepting_Selector'Access,
Status => Selector_Status
);
exit when Selector_Status = GNAT.Sockets.Aborted;
if Selector_Status = GNAT.Sockets.Completed then
Ada.Text_IO.Put_Line (
"Client from " & GNAT.Sockets.Image (Client_Address)
);
String'Write (
GNAT.Sockets.Stream (Client_Socket),
"Hello!" & ASCII.CR & ASCII.LF
);
GNAT.Sockets.Close_Socket (Client_Socket);
end if;
end loop;
GNAT.Sockets.Close_Socket (Listener_Socket);
end Start;
procedure Stop
(S : in out Server)
is
begin
Ada.Text_IO.Put_Line ("");
Ada.Text_IO.Put_Line ("Stopping...");
GNAT.Sockets.Abort_Selector (S.Accepting_Selector);
end Stop;
overriding
procedure Initialize
(Object : in out Server)
is
begin
GNAT.Sockets.Create_Selector (Object.Accepting_Selector);
end Initialize;
overriding
procedure Finalize
(Object : in out Server)
is
begin
GNAT.Sockets.Close_Selector (Object.Accepting_Selector);
end Finalize;
end Servers;
with Ada.Finalization;
with GNAT.Sockets;
package Servers is
type Server is new Ada.Finalization.Limited_Controlled with private;
procedure Start
(S : in out Server);
procedure Stop
(S : in out Server);
private
type Server is new Ada.Finalization.Limited_Controlled with record
Accepting_Selector : aliased GNAT.Sockets.Selector_Type;
end record;
overriding
procedure Initialize
(Object : in out Server);
overriding
procedure Finalize
(Object : in out Server);
end Servers;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment