comp.lang.ada
 help / color / mirror / Atom feed
* How to implement a server socket compatible to telnet?
@ 2008-08-08 11:31 snoopysalive
  2008-08-08 13:15 ` Jeffrey Creem
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: snoopysalive @ 2008-08-08 11:31 UTC (permalink / raw)


Hello!

For some reasons I had to implement a server socket in C++. Now I want
to do the same in Ada and so I read the GNAT.Sockets-library and
implemented a shorter version of the example given in the g-
socket.ads.

The problem is that I want to implement the server in a kind, that
processes written in other languages like the tool telnet or a Java-
programme are able to communicate with it. But my server isn't able to
print a message sent by the telnet-client, so I think that I've
written something wrong in my code.

Here's the code:

with Ada.Text_IO,
     Ada.Exceptions,
     GNAT.Sockets;
use Ada.Text_IO,
    Ada.Exceptions,
    GNAT.Sockets;

procedure Server is
    Host    : String    := "localhost";
    Port    : Port_Type := 7777;
    Address : Sock_Addr_Type;
    Server  : Socket_Type;
    Client  : Socket_Type;
    Channel : Stream_Access;
begin -- Server
    Initialize;
    Address.Addr := Addresses (Get_Host_By_Name (Host), 1);
    Address.Port := Port;

    begin
        Create_Socket (Server);
        Put_Line ("Server socket created");
    exception
        when E : Socket_Error =>
            Put_Line (Standard_Error, "Create_Socket failed");
    end;
    -- Create server socket

    begin
        Set_Socket_Option (Server, Socket_Level, (Reuse_Address,
True));
        Put_Line ("Socket address reused");
    exception
        when E : Socket_Error =>
            Put_Line (Standard_Error, "Set_Socket_Option failed");
    end;
    -- Resuse socket address

    begin
        Bind_Socket (Server, Address);
        Put_Line ("Server socket bound");
    exception
        when E : Socket_Error =>
            Put_Line (Standard_Error, "Bind_Socket failed");
    end;
    -- Bind server

    begin
        Listen_Socket (Server);
        Put ("Server is listening... ");
    exception
        when E : Socket_Error =>
            Put_Line (Standard_Error, "Listen_Socket failed");
    end;
    -- Listening...

    begin
        Accept_Socket (Server, Client, Address);
        Put_Line ("Got client connection");
        delay 0.2;
        Channel := Stream (Client);
        Put_Line ("Client streamed");

        declare
            Message : String := String'input (Channel);
        begin
            Put_Line (Message);
        end;
        -- Get client message and print it to the screen

    exception
        when E : Socket_Error =>
            Put_Line (Standard_Error, "Accept_Socket failed");
    end;
    -- Client handling

    begin
        Close_Socket (Client);
        Put_Line ("Client closed");
        Close_Socket (Server);
        Put_Line ("Server closed");
    exception
        when E : Socket_Error =>
            Put_Line (Standard_Error, "Close_Socket failed");
    end;
    -- Close client and server sockets

    Finalize;
end Server;


The server's output is:

"Server socket created
Socket address reused
Server socket bound
Server is listening... Got client connection
Client streamed

Client closed
Server closed"


The empty line should be the message sent by telnet, but like you can
see, the message is empty.

So, can anybody explain to me, what I have done wrong?

Thank you,
Matthias



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-08 11:31 How to implement a server socket compatible to telnet? snoopysalive
@ 2008-08-08 13:15 ` Jeffrey Creem
  2008-08-08 13:35 ` Alex R. Mosteo
  2008-08-08 16:24 ` anon
  2 siblings, 0 replies; 12+ messages in thread
From: Jeffrey Creem @ 2008-08-08 13:15 UTC (permalink / raw)


snoopysalive@googlemail.com wrote:
> Hello!
> 
> For some reasons I had to implement a server socket in C++. Now I want
> to do the same in Ada and so I read the GNAT.Sockets-library and
> implemented a shorter version of the example given in the g-
> socket.ads.
> 
> The problem is that I want to implement the server in a kind, that
> processes written in other languages like the tool telnet or a Java-
> programme are able to communicate with it. But my server isn't able to
> print a message sent by the telnet-client, so I think that I've
> written something wrong in my code.
> 


You don't show the client code but if you really really mean it is a 
telnet client then your problem is that  you are using 'input. Look at 
the LRM definitions for these. (looking at ada 95 here for a moment, 
ARM95-13-13-2)

S'Input reads and returns one value from Stream, using any bounds or 
discriminants written by a corresponding S'Output to determine how much 
to read.

So, unless your telnet client is Ada aware and is sending strings 
formatted per Ada string semantics with bounds, then this can't work. 
The example you started from probably had a client and server who had 
agreed upon a protocol that used 'input 'output semantics.

Telnet has not agreed to this protocol.

There are plenty of ways to do what you are trying.

You could probably play around with 'read 'write on characters or with

  procedure Receive_Socket
      (Socket : Socket_Type;
       Item   : out Ada.Streams.Stream_Element_Array;
       Last   : out Ada.Streams.Stream_Element_Offset);

or with a custom overloaded 'read that you implement with something like 
Receive_Socket depending upon what you are trying to accomplish.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-08 11:31 How to implement a server socket compatible to telnet? snoopysalive
  2008-08-08 13:15 ` Jeffrey Creem
@ 2008-08-08 13:35 ` Alex R. Mosteo
  2008-08-08 16:24 ` anon
  2 siblings, 0 replies; 12+ messages in thread
From: Alex R. Mosteo @ 2008-08-08 13:35 UTC (permalink / raw)


snoopysalive@googlemail.com wrote:

> Hello!
> 
> For some reasons I had to implement a server socket in C++. Now I want
> to do the same in Ada and so I read the GNAT.Sockets-library and
> implemented a shorter version of the example given in the g-
> socket.ads.
> 
> The problem is that I want to implement the server in a kind, that
> processes written in other languages like the tool telnet or a Java-
> programme are able to communicate with it. But my server isn't able to
> print a message sent by the telnet-client, so I think that I've
> written something wrong in my code.
> 
> Here's the code:
> 
> with Ada.Text_IO,
>      Ada.Exceptions,
>      GNAT.Sockets;
> use Ada.Text_IO,
>     Ada.Exceptions,
>     GNAT.Sockets;
> 
> procedure Server is
>     Host    : String    := "localhost";
>     Port    : Port_Type := 7777;
>     Address : Sock_Addr_Type;
>     Server  : Socket_Type;
>     Client  : Socket_Type;
>     Channel : Stream_Access;
> begin -- Server
>     Initialize;
>     Address.Addr := Addresses (Get_Host_By_Name (Host), 1);
>     Address.Port := Port;
> 
>     begin
>         Create_Socket (Server);
>         Put_Line ("Server socket created");
>     exception
>         when E : Socket_Error =>
>             Put_Line (Standard_Error, "Create_Socket failed");
>     end;
>     -- Create server socket
> 
>     begin
>         Set_Socket_Option (Server, Socket_Level, (Reuse_Address,
> True));
>         Put_Line ("Socket address reused");
>     exception
>         when E : Socket_Error =>
>             Put_Line (Standard_Error, "Set_Socket_Option failed");
>     end;
>     -- Resuse socket address
> 
>     begin
>         Bind_Socket (Server, Address);
>         Put_Line ("Server socket bound");
>     exception
>         when E : Socket_Error =>
>             Put_Line (Standard_Error, "Bind_Socket failed");
>     end;
>     -- Bind server
> 
>     begin
>         Listen_Socket (Server);
>         Put ("Server is listening... ");
>     exception
>         when E : Socket_Error =>
>             Put_Line (Standard_Error, "Listen_Socket failed");
>     end;
>     -- Listening...
> 
>     begin
>         Accept_Socket (Server, Client, Address);
>         Put_Line ("Got client connection");
>         delay 0.2;
>         Channel := Stream (Client);
>         Put_Line ("Client streamed");
> 
>         declare
>             Message : String := String'input (Channel);

My bet is the problem is here above: by using String'Input, you're first trying
to read the bounds of the array. A foreign telnet client won't send
Ada-compliant arrays, but characters one by one.

You can't either use String'Read because you don't know in advance the line
length. So I'd change this to manually read one character at a time until end
of line is detected.

>         begin
>             Put_Line (Message);
>         end;
>         -- Get client message and print it to the screen
> 
>     exception
>         when E : Socket_Error =>
>             Put_Line (Standard_Error, "Accept_Socket failed");
>     end;
>     -- Client handling
> 
>     begin
>         Close_Socket (Client);
>         Put_Line ("Client closed");
>         Close_Socket (Server);
>         Put_Line ("Server closed");
>     exception
>         when E : Socket_Error =>
>             Put_Line (Standard_Error, "Close_Socket failed");
>     end;
>     -- Close client and server sockets
> 
>     Finalize;
> end Server;
> 
> 
> The server's output is:
> 
> "Server socket created
> Socket address reused
> Server socket bound
> Server is listening... Got client connection
> Client streamed
> 
> Client closed
> Server closed"
> 
> 
> The empty line should be the message sent by telnet, but like you can
> see, the message is empty.
> 
> So, can anybody explain to me, what I have done wrong?
> 
> Thank you,
> Matthias




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-08 11:31 How to implement a server socket compatible to telnet? snoopysalive
  2008-08-08 13:15 ` Jeffrey Creem
  2008-08-08 13:35 ` Alex R. Mosteo
@ 2008-08-08 16:24 ` anon
  2008-08-09 13:19   ` snoopysalive
  2008-08-10 22:15   ` Robert A Duff
  2 siblings, 2 replies; 12+ messages in thread
From: anon @ 2008-08-08 16:24 UTC (permalink / raw)


If your doing a direct conversion from C to Ada using sockets then you might 
need to use the lower-level socket package, "GNAT.Sockets.Thin".  This 
package has direct library links to the sockets library routines, bypassing the 
extra layer of code in "GNAT.Sockets".

Also, in "GNAT.Sockets.Thin", the "Bind" function is called "C_Bind" and is 
still a function unlike "sockets where the sockets routines are mostly 
procedures and are based on "Ada.Streams", in "GNAT.Sockets".

In <ca7b2304-6726-479b-89a0-67486c3dc06f@f63g2000hsf.googlegroups.com>, "snoopysalive@googlemail.com" <snoopysalive@googlemail.com> writes:
>Hello!
>
>For some reasons I had to implement a server socket in C++. Now I want
>to do the same in Ada and so I read the GNAT.Sockets-library and
>implemented a shorter version of the example given in the g-
>socket.ads.
>
>The problem is that I want to implement the server in a kind, that
>processes written in other languages like the tool telnet or a Java-
>programme are able to communicate with it. But my server isn't able to
>print a message sent by the telnet-client, so I think that I've
>written something wrong in my code.
>
>Here's the code:
>
>with Ada.Text_IO,
>     Ada.Exceptions,
>     GNAT.Sockets;
>use Ada.Text_IO,
>    Ada.Exceptions,
>    GNAT.Sockets;
>
>procedure Server is
>    Host    : String    := "localhost";
>    Port    : Port_Type := 7777;
>    Address : Sock_Addr_Type;
>    Server  : Socket_Type;
>    Client  : Socket_Type;
>    Channel : Stream_Access;
>begin -- Server
>    Initialize;
>    Address.Addr := Addresses (Get_Host_By_Name (Host), 1);
>    Address.Port := Port;
>
>    begin
>        Create_Socket (Server);
>        Put_Line ("Server socket created");
>    exception
>        when E : Socket_Error =>
>            Put_Line (Standard_Error, "Create_Socket failed");
>    end;
>    -- Create server socket
>
>    begin
>        Set_Socket_Option (Server, Socket_Level, (Reuse_Address,
>True));
>        Put_Line ("Socket address reused");
>    exception
>        when E : Socket_Error =>
>            Put_Line (Standard_Error, "Set_Socket_Option failed");
>    end;
>    -- Resuse socket address
>
>    begin
>        Bind_Socket (Server, Address);
>        Put_Line ("Server socket bound");
>    exception
>        when E : Socket_Error =>
>            Put_Line (Standard_Error, "Bind_Socket failed");
>    end;
>    -- Bind server
>
>    begin
>        Listen_Socket (Server);
>        Put ("Server is listening... ");
>    exception
>        when E : Socket_Error =>
>            Put_Line (Standard_Error, "Listen_Socket failed");
>    end;
>    -- Listening...
>
>    begin
>        Accept_Socket (Server, Client, Address);
>        Put_Line ("Got client connection");
>        delay 0.2;
>        Channel := Stream (Client);
>        Put_Line ("Client streamed");
>
>        declare
>            Message : String := String'input (Channel);
>        begin
>            Put_Line (Message);
>        end;
>        -- Get client message and print it to the screen
>
>    exception
>        when E : Socket_Error =>
>            Put_Line (Standard_Error, "Accept_Socket failed");
>    end;
>    -- Client handling
>
>    begin
>        Close_Socket (Client);
>        Put_Line ("Client closed");
>        Close_Socket (Server);
>        Put_Line ("Server closed");
>    exception
>        when E : Socket_Error =>
>            Put_Line (Standard_Error, "Close_Socket failed");
>    end;
>    -- Close client and server sockets
>
>    Finalize;
>end Server;
>
>
>The server's output is:
>
>"Server socket created
>Socket address reused
>Server socket bound
>Server is listening... Got client connection
>Client streamed
>
>Client closed
>Server closed"
>
>
>The empty line should be the message sent by telnet, but like you can
>see, the message is empty.
>
>So, can anybody explain to me, what I have done wrong?
>
>Thank you,
>Matthias




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-08 16:24 ` anon
@ 2008-08-09 13:19   ` snoopysalive
  2008-08-10 22:15   ` Robert A Duff
  1 sibling, 0 replies; 12+ messages in thread
From: snoopysalive @ 2008-08-09 13:19 UTC (permalink / raw)


Thanks to all the answers of you three. Actually, I also suspected
that the problem could have something to do sort of incompatibility of
programmes written in C and those written in Ada. So, I'll try out
your solution hints. Thank you!



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-08 16:24 ` anon
  2008-08-09 13:19   ` snoopysalive
@ 2008-08-10 22:15   ` Robert A Duff
  2008-08-10 23:34     ` anon
  1 sibling, 1 reply; 12+ messages in thread
From: Robert A Duff @ 2008-08-10 22:15 UTC (permalink / raw)


anon@anon.org (anon) writes:

> If your doing a direct conversion from C to Ada using sockets then you
> might need to use the lower-level socket package, "GNAT.Sockets.Thin".
> This package has direct library links to the sockets library routines,
> bypassing the extra layer of code in "GNAT.Sockets".

GNAT.Sockets.Thin says:

--  This package provides a target dependent thin interface to the sockets
--  layer for use by the GNAT.Sockets package (g-socket.ads). This package
--  should not be directly with'ed by an applications program.

which means that AdaCore feels free to change the interface in
incompatible ways at any time.

- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-10 22:15   ` Robert A Duff
@ 2008-08-10 23:34     ` anon
  2008-08-11  1:31       ` Robert A Duff
  0 siblings, 1 reply; 12+ messages in thread
From: anon @ 2008-08-10 23:34 UTC (permalink / raw)


What's your point? "GNAT.Sockets.Thin" is a universal interface to the 
system socket library just like "Interface.C" is for interfacing C code. Plus, 
most socket routines are standardized, in todays OS.  Only the single 
"GNAT.Sockets.Constants" file is altered, due to system control flags, but 
most of the constants that are used for normal socket functions are 
standardized as well. 

And since Adacore (GNAT) is the only game around for Ada-2005 specs 
there is no reason to get upset with portability because what vendor would 
you port your code to!


In <wccsktcecuk.fsf@shell01.TheWorld.com>, Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>anon@anon.org (anon) writes:
>
>> If your doing a direct conversion from C to Ada using sockets then you
>> might need to use the lower-level socket package, "GNAT.Sockets.Thin".
>> This package has direct library links to the sockets library routines,
>> bypassing the extra layer of code in "GNAT.Sockets".
>
>GNAT.Sockets.Thin says:
>
>--  This package provides a target dependent thin interface to the sockets
>--  layer for use by the GNAT.Sockets package (g-socket.ads). This package
>--  should not be directly with'ed by an applications program.
>
>which means that AdaCore feels free to change the interface in
>incompatible ways at any time.
>
>- Bob




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-10 23:34     ` anon
@ 2008-08-11  1:31       ` Robert A Duff
  2008-08-11 18:26         ` anon
  0 siblings, 1 reply; 12+ messages in thread
From: Robert A Duff @ 2008-08-11  1:31 UTC (permalink / raw)


anon@anon.org (anon) writes:

> What's your point?

My point is that AdaCore might change the interface GNAT.Sockets.Thin
on whim, whereas it won't change the interface GNAT.Sockets so easily,
since the latter is a documented interface.  That's all -- if you're
happy with such, use GNAT.Sockets.Thin as you like.

>... "GNAT.Sockets.Thin" is a universal interface to the 
> system socket library just like "Interface.C" is for interfacing C code. Plus, 
> most socket routines are standardized, in todays OS.  Only the single 
> "GNAT.Sockets.Constants" file is altered, due to system control flags, but 
> most of the constants that are used for normal socket functions are 
> standardized as well. 
>
> And since Adacore (GNAT) is the only game around for Ada-2005 specs 
> there is no reason to get upset with portability because what vendor would 
> you port your code to!
>
>
> In <wccsktcecuk.fsf@shell01.TheWorld.com>, Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>>anon@anon.org (anon) writes:
>>
>>> If your doing a direct conversion from C to Ada using sockets then you
>>> might need to use the lower-level socket package, "GNAT.Sockets.Thin".
>>> This package has direct library links to the sockets library routines,
>>> bypassing the extra layer of code in "GNAT.Sockets".
>>
>>GNAT.Sockets.Thin says:
>>
>>--  This package provides a target dependent thin interface to the sockets
>>--  layer for use by the GNAT.Sockets package (g-socket.ads). This package
>>--  should not be directly with'ed by an applications program.
>>
>>which means that AdaCore feels free to change the interface in
>>incompatible ways at any time.
>>
>>- Bob



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-11  1:31       ` Robert A Duff
@ 2008-08-11 18:26         ` anon
  2008-08-11 18:59           ` Samuel Tardieu
  0 siblings, 1 reply; 12+ messages in thread
From: anon @ 2008-08-11 18:26 UTC (permalink / raw)


Your just trying to make Trouble and Destroy Ada!  Because in that concept 
you should NEVER use "GNAT.Sockets" either.  That means that Ada will be 
cripple because it will NEVER be able to use the Internet or Com ports, or 
USB because those I/O packages are not define in the RM.  Because these 
extra hardware packages are not apart of the RM they must be defined 
somewhere, and Adacore has choosen to places these hardware packages in 
its GNAT subpackages.  And in most cases they use "STADARDIZE" calls 
into the OS or hardware. But in you concept the only hardware I/O package 
for GNAT Ada are disk, keyboard, or simple video aka basically OS and BIOS 
I/O calls. But a language must have I/O and the ability to expand beyond its 
RM or it DIES! But may be that's what you want!

This "STADARDIZE" calls concepts explains one reason why the UART 
package has taken so long to become apart of the GNAT system,  there is 
no true standards on calls for the UART even though the ports and functions 
have been well defined for years.

And there is only vendor that does not maintains a level of Standardizing 
behavior, and that is Sun with Java.  In evey new version of Java there are 
some routines that have been "DEPRECATED", but most people do not say 
"DO NOT USE" that routine or package because SUN may change it.  That's 
because those progammers and uses want JAVA to be succeed.

So, if you want GNAT Ada to succeed as well, do not cut any package down.  
You should show the person who ask the question how it should be done. And 
in this case, either by writing code, given a package. Or posting a link to a 
telnet program written in Ada that they can download and check out for 
themselves.



In <wcctzds5oc4.fsf@shell01.TheWorld.com>, Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>anon@anon.org (anon) writes:
>
>> What's your point?
>
>My point is that AdaCore might change the interface GNAT.Sockets.Thin
>on whim, whereas it won't change the interface GNAT.Sockets so easily,
>since the latter is a documented interface.  That's all -- if you're
>happy with such, use GNAT.Sockets.Thin as you like.
>
>>... "GNAT.Sockets.Thin" is a universal interface to the 
>> system socket library just like "Interface.C" is for interfacing C code. Plus, 
>> most socket routines are standardized, in todays OS.  Only the single 
>> "GNAT.Sockets.Constants" file is altered, due to system control flags, but 
>> most of the constants that are used for normal socket functions are 
>> standardized as well. 
>>
>> And since Adacore (GNAT) is the only game around for Ada-2005 specs 
>> there is no reason to get upset with portability because what vendor would 
>> you port your code to!
>>
>>
>> In <wccsktcecuk.fsf@shell01.TheWorld.com>, Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>>>anon@anon.org (anon) writes:
>>>
>>>> If your doing a direct conversion from C to Ada using sockets then you
>>>> might need to use the lower-level socket package, "GNAT.Sockets.Thin".
>>>> This package has direct library links to the sockets library routines,
>>>> bypassing the extra layer of code in "GNAT.Sockets".
>>>
>>>GNAT.Sockets.Thin says:
>>>
>>>--  This package provides a target dependent thin interface to the sockets
>>>--  layer for use by the GNAT.Sockets package (g-socket.ads). This package
>>>--  should not be directly with'ed by an applications program.
>>>
>>>which means that AdaCore feels free to change the interface in
>>>incompatible ways at any time.
>>>
>>>- Bob




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-11 18:26         ` anon
@ 2008-08-11 18:59           ` Samuel Tardieu
  2008-08-20 21:25             ` snoopysalive
  0 siblings, 1 reply; 12+ messages in thread
From: Samuel Tardieu @ 2008-08-11 18:59 UTC (permalink / raw)


>>>>> "anon" == anon  <anon@anon.org> writes:

anon> You should show the person who ask the question how it should be
anon> done. And in this case, either by writing code, given a
anon> package. Or posting a link to a telnet program written in Ada
anon> that they can download and check out for themselves.

Wow, good advice! Why didn't you follow it yourself? Where is your
code or your link?

You're a troll.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-11 18:59           ` Samuel Tardieu
@ 2008-08-20 21:25             ` snoopysalive
  2008-08-20 22:57               ` anon
  0 siblings, 1 reply; 12+ messages in thread
From: snoopysalive @ 2008-08-20 21:25 UTC (permalink / raw)


Come on guys, stop arguing. In the end, I've found a solution:

-----------------------------------------------------------------------
with Ada.Text_IO,
     Ada.Exceptions,
	 Ada.Streams,
	 Ada.Unchecked_Deallocation,
     GNAT.Sockets;
use Ada.Text_IO,
    Ada.Exceptions,
    Ada.Streams,
    GNAT.Sockets;

procedure IP_Server is

	BUFFER_SIZE : constant Positive := 1024;

	type String_Access is access all String;

	procedure Free is new Ada.Unchecked_Deallocation
		(String, String_Access);

	CRLF : constant String := ASCII.CR & ASCII.LF;
	Host : constant String := "localhost";
	Port : Port_Type       := 7777;

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

	Data   : Stream_Element_Array (1..1);
	Offset : Stream_Element_Count;

	Buffer : String_Access := new String (1..BUFFER_SIZE);
	Cnt    : Natural := 0;

	Test : Float := 0.0;

begin -- IP_Server
	Initialize;

	Address.Addr := Addresses (Get_Host_By_Name (Host), 1);
	Address.Port := Port;

	Create_Socket (Server);
	Set_Socket_Option (Server, Socket_Level, (Reuse_Address, True));
	Bind_Socket (Server, Address);
	Listen_Socket (Server);
	Accept_Socket (Server, Client, Address);
	Channel := Stream (Client);

	Cnt := 0;
	loop
		Read (Channel.all, Data (1..1), Offset);
		if Character'Val (Data (1)) = ASCII.CR  or
		   Character'Val (Data (1)) = ASCII.LF  or
		   Character'Val (Data (1)) = ASCII.NUL or
		   Offset = 0 then
			exit;
		else
			Cnt := Cnt + 1;
			Buffer.all (Cnt) := Character'Val (Data (1));
		end if;
	end loop;
	-- Read values from client-stream character by character.
	-- Reading should be stopped when Windows-linefeed or
	-- NULL was found, because telnet seams to be sending
	-- strings in a Windows-like format including the
	-- terminating \0-character known from C-strings.

	declare
		Old : String_Access := Buffer;
	begin
		Buffer := new String'(Buffer (1..Cnt));
		Free (Old);
	end;
	-- The buffer-size of Str is 1024 elements. It's necessary
	-- to create a new String containing only relevant characters
	-- for being able to process the message further.

	declare
		Pong : String := "pong" & CRLF;
		O    : Stream_Element_Array (1..Pong'length);
	begin
		if Buffer.all = "ping" then
			for I in Pong'range loop
				O (Stream_Element_Offset (I)) := Character'Pos (Pong (I));
			end loop;
			Write (Channel.all, O);
		end if;
	end;
	-- If Buffer's message equals "ping" the server will
	-- send "pong" to the client. "pong" must be casted
	-- from String to Stream_Element_Array first.

	Close_Socket (Client);
	Close_Socket (Server);

	Finalize;

exception when E : Socket_Error =>
	Put_Line (Standard_Error, "Socket_Error => " & Exception_Message
(E));

end IP_Server;
-----------------------------------------------------------------------------------

Thanks to the thread under http://groups.google.com/group/comp.lang.ada/browse_thread/thread/c58b7bd180ea81b2
I found out how to read character by character from the client.
However, it's not very comfortable to cast the echo-string manually
but it's better than not being able to communicate with telnet or
other C-based clients.

Bye,
Matthias



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to implement a server socket compatible to telnet?
  2008-08-20 21:25             ` snoopysalive
@ 2008-08-20 22:57               ` anon
  0 siblings, 0 replies; 12+ messages in thread
From: anon @ 2008-08-20 22:57 UTC (permalink / raw)


But he wants to deal with Telnet.  It states that in the title.

And actually, a complete program PingPong is coded in the file 
"GNAT.Sockets.ads " which deals with both server and client code. 

Like I say KNOW your compiler and its packages That way you might be 
able to skip spending time seaching the internet or books.


In <0baa592d-1291-4298-90e3-88ca85a476a8@k13g2000hse.googlegroups.com>, "snoopysalive@googlemail.com" <snoopysalive@googlemail.com> writes:
>Come on guys, stop arguing. In the end, I've found a solution:
>
>-----------------------------------------------------------------------
>with Ada.Text_IO,
>     Ada.Exceptions,
>	 Ada.Streams,
>	 Ada.Unchecked_Deallocation,
>     GNAT.Sockets;
>use Ada.Text_IO,
>    Ada.Exceptions,
>    Ada.Streams,
>    GNAT.Sockets;
>
>procedure IP_Server is
>
>	BUFFER_SIZE : constant Positive := 1024;
>
>	type String_Access is access all String;
>
>	procedure Free is new Ada.Unchecked_Deallocation
>		(String, String_Access);
>
>	CRLF : constant String := ASCII.CR & ASCII.LF;
>	Host : constant String := "localhost";
>	Port : Port_Type       := 7777;
>
>	Address : Sock_Addr_Type;
>	Server  : Socket_Type;
>	Client  : Socket_Type;
>	Channel : Stream_Access;
>
>	Data   : Stream_Element_Array (1..1);
>	Offset : Stream_Element_Count;
>
>	Buffer : String_Access := new String (1..BUFFER_SIZE);
>	Cnt    : Natural := 0;
>
>	Test : Float := 0.0;
>
>begin -- IP_Server
>	Initialize;
>
>	Address.Addr := Addresses (Get_Host_By_Name (Host), 1);
>	Address.Port := Port;
>
>	Create_Socket (Server);
>	Set_Socket_Option (Server, Socket_Level, (Reuse_Address, True));
>	Bind_Socket (Server, Address);
>	Listen_Socket (Server);
>	Accept_Socket (Server, Client, Address);
>	Channel := Stream (Client);
>
>	Cnt := 0;
>	loop
>		Read (Channel.all, Data (1..1), Offset);
>		if Character'Val (Data (1)) = ASCII.CR  or
>		   Character'Val (Data (1)) = ASCII.LF  or
>		   Character'Val (Data (1)) = ASCII.NUL or
>		   Offset = 0 then
>			exit;
>		else
>			Cnt := Cnt + 1;
>			Buffer.all (Cnt) := Character'Val (Data (1));
>		end if;
>	end loop;
>	-- Read values from client-stream character by character.
>	-- Reading should be stopped when Windows-linefeed or
>	-- NULL was found, because telnet seams to be sending
>	-- strings in a Windows-like format including the
>	-- terminating \0-character known from C-strings.
>
>	declare
>		Old : String_Access := Buffer;
>	begin
>		Buffer := new String'(Buffer (1..Cnt));
>		Free (Old);
>	end;
>	-- The buffer-size of Str is 1024 elements. It's necessary
>	-- to create a new String containing only relevant characters
>	-- for being able to process the message further.
>
>	declare
>		Pong : String := "pong" & CRLF;
>		O    : Stream_Element_Array (1..Pong'length);
>	begin
>		if Buffer.all = "ping" then
>			for I in Pong'range loop
>				O (Stream_Element_Offset (I)) := Character'Pos (Pong (I));
>			end loop;
>			Write (Channel.all, O);
>		end if;
>	end;
>	-- If Buffer's message equals "ping" the server will
>	-- send "pong" to the client. "pong" must be casted
>	-- from String to Stream_Element_Array first.
>
>	Close_Socket (Client);
>	Close_Socket (Server);
>
>	Finalize;
>
>exception when E : Socket_Error =>
>	Put_Line (Standard_Error, "Socket_Error => " & Exception_Message
>(E));
>
>end IP_Server;
>-----------------------------------------------------------------------------------
>
>Thanks to the thread under http://groups.google.com/group/comp.lang.ada/browse_thread/thread/c58b7bd180ea81b2
>I found out how to read character by character from the client.
>However, it's not very comfortable to cast the echo-string manually
>but it's better than not being able to communicate with telnet or
>other C-based clients.
>
>Bye,
>Matthias




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-08-20 22:57 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-08 11:31 How to implement a server socket compatible to telnet? snoopysalive
2008-08-08 13:15 ` Jeffrey Creem
2008-08-08 13:35 ` Alex R. Mosteo
2008-08-08 16:24 ` anon
2008-08-09 13:19   ` snoopysalive
2008-08-10 22:15   ` Robert A Duff
2008-08-10 23:34     ` anon
2008-08-11  1:31       ` Robert A Duff
2008-08-11 18:26         ` anon
2008-08-11 18:59           ` Samuel Tardieu
2008-08-20 21:25             ` snoopysalive
2008-08-20 22:57               ` anon

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