client <-> server interaction in C

Tapio Kelloniemi persistent.spam at thack.org
Tue Nov 22 14:06:05 PST 2005


On Tue, Nov 22, 2005 at 02:02:49PM -0500, Jeremy Huntwork wrote:
 > As of right now, my vote is C and only XML if its shown to be *very* 
 > advantageous. I'd personally rather not mess with it.

My vote is against C (and all variants of it), because I don't want to 
run alfsd in GDB to catch the segfaults. Well, my whole system is 
written in C and I don't run Linux in GDB, but seriously it is much easier to 
write buggy code in C than in other languages.

Attached are the client and server programs so far seen in C and in 
Python, but now in Ada2005. As opposed to the C version, these are much 
more readable, and a bit larger (when comparing the number of bytes in 
the source codes). Note that the Ada version has full error checking, 
though there is no single line in the code to deal with errors. The only 
thing which can make these programs crash is sending a message so big
that it will cause a stack overflow.

I really don't believe that anybody (except I) would be interested in 
programming in Ada, but just in case...

Compileing:
# gnatmake client
# gnatmake server

Running:
# ./server
(will wait fro connection)
# ./client 127.0.0.1 "Any message"

-- 
Tapio
-------------- next part --------------
with GNAT.Sockets; --  Include socket library
with Ada.Text_IO; -- For printing out diagnostic messages

procedure Server is

   use GNAT.Sockets; --  Make symbols of Sockets directly visible

   Listen, Connection : Socket_Type;
   Address : Sock_Addr_Type;
   Channel : Stream_Access; -- I/O channel is a pointer (access) to a stream

begin
   --  Initialise sockets API. This is not required in Linux, but for
   --  portability...
   Initialize; --  We could have written GNAT.Sockets.Initialize;

   --  First create the listening socket
   Create_Socket (Listen);

   --  Set up an address and bind it to the server socket
   Address.Addr := Inet_Addr ("127.0.0.1");
   Address.Port := 9191;
   Bind_Socket (Listen, Address);

   --  Listen server socket for incoming connections, and accept the first one
   Listen_Socket (Listen);
   Accept_Socket (Listen, Connection, Address);

   --  Get a pointer to the I/O stream of the socket
   Channel := Stream (Connection);

   --  Print a diagnostic message
   Ada.Text_IO.Put_Line ("Server: Connection from " & Image (Address.Addr));

   --  Read a message from the socket and print it out, this is done in
   --  a subblock so that we can have a message of any length (no need
   --  to specify fixed buffer size as in the C version).
   declare
      Message : String := String'Input (Channel);
      --  NOTE: Declaration and initialisation at once, size of Message
      --  is decided at run time.
   begin
      Ada.Text_IO.Put_Line ("Received: " & Message);

      --  Write the messagte back to the socket
      String'Output (Channel, "Got (" & Message & ")");
   end;

   --  Close sockets and free the I/O stream
   Close_Socket (Connection);
   Free (Channel);
   Close_Socket (Listen);

   --  Do API finalisation. Again, not needed in Linux...
   Finalize;
end Server;
-------------- next part --------------
with GNAT.Sockets; use GNAT.Sockets; --  Import the socket library
with Ada.Text_IO;
with Ada.Command_Line; --  For reading command-line parameters

procedure Client is

   Socket : Socket_Type;
   Channel : Stream_Access;
   Address : Sock_Addr_Type;

begin
   --  Check if the number of arguments is not 2 and exit, if it is not.
   if Ada.Command_Line.Argument_Count /= 2 then
      Ada.Text_IO.Put_Line ("Usage: client <server> <message>");
      return;
   end if;

   --  Initialise sockets API
   Initialize;

   --  Create a socket
   Create_Socket (Socket);

   --  Setup address (read host address from command line)
   Address.Addr := Inet_Addr (Ada.Command_Line.Argument (1));
   Address.Port := 9191;

   --  Conect to the server
   Connect_Socket (Socket, Address);

   --  Get pointer to the socket's I/O stream
   Channel := Stream (Socket);

   --  Send a message to the socket
   String'Output (Channel, Ada.Command_Line.Argument (2));

   --  Read a message from socket and display it immediately. Note again
   --  how the message can be of any length.
   Ada.Text_IO.Put_Line ("Received message: " & String'Input (Channel));

   --  Do uninitialisations
   Close_Socket (Socket);
   Free (Channel);

   --  Finalise sockets API
   Finalize;
end Client;


More information about the alfs-discuss mailing list