comp.lang.ada
 help / color / mirror / Atom feed
* GNAT.Sockets Problems
@ 2003-05-09 19:46 file13
  2003-05-11  0:51 ` Craig Carey
  2003-05-12 11:38 ` Simon Clubley
  0 siblings, 2 replies; 3+ messages in thread
From: file13 @ 2003-05-09 19:46 UTC (permalink / raw)


Howdy all, I've been tinkering with GNAT.Sockets on Mandrake 9.1 using
the Gnat-3.15p linux binary and I'm simply trying to write the first
day time client from Stevens UNIX Network Programming book with it and
I can't seem to figure out what I'm doing wrong.  The server I've
tested on is the following one from Steven's book (it's in C):

#include        <sys/types.h>   /* basic system data types */
#include        <sys/socket.h>  /* basic socket definitions */
#include        <netinet/in.h>  /* sockaddr_in{} and other Internet
defns */
#include        <arpa/inet.h>   /* inet(3) functions */
#include        <unistd.h>
#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>
#include        <time.h>

#define MAXLINE         4096    /* max text line length */
#define SA      struct sockaddr
#define LISTENQ         1024    /* 2nd argument to listen() */

int main(int argc, char **argv) {
  int listenfd, connfd;
  struct sockaddr_in servaddr;
  char buff[MAXLINE];
  time_t ticks;

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family      = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port        = htons(13); /* daytime server */


  bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

  listen(listenfd, LISTENQ);

  for ( ; ; ) {
    connfd = accept(listenfd, (SA *) NULL, NULL);

    ticks = time(NULL);
    snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
    write(connfd, buff, strlen(buff));

    close(connfd);
  }
}

I've tested it with the following accompanying C client code and it
works fine:

#include        <sys/types.h>   /* basic system data types */
#include        <sys/socket.h>  /* basic socket definitions */
#include        <netinet/in.h>  /* sockaddr_in{} and other Internet
defns */
#include        <arpa/inet.h>   /* inet(3) functions */
#include        <unistd.h>
#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>

#define MAXLINE         4096    /* max text line length */
#define SA      struct sockaddr

int main(int argc, char **argv) {
  int sockfd, n;
  char recvline[MAXLINE + 1];
  struct sockaddr_in    servaddr;

  if (argc != 2)
    puts("usage: a.out <IPaddress>");

  if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    puts("socket error");

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port   = htons(13);      /* daytime server */
  if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
    printf("inet_pton error for %s", argv[1]);

  if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
    puts("connect error");

  while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
    recvline[n] = 0;    /* null terminate */
    if (fputs(recvline, stdout) == EOF)
      puts("fputs error");
  }
  if (n < 0)
    puts("read error");

  exit(0);
}

$ ./daytimetcpcli 127.0.0.1
Fri May  9 14:37:41 2003

so far in Ada I have:

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

procedure Daytime_Client is
   Target  : Inet_Addr_Type := Inet_Addr ("127.0.0.1");
   Socket  : Socket_Type;
   Server  : Sock_Addr_Type;
   Channel : Stream_Access;
begin
   Initialize;
   Create_Socket (Socket);
   Server := (Family_Inet, Target, 13);

   Connect_Socket (Socket, Server);

   Channel := Stream (Socket, Server);
   Put_Line (String'Input (Channel));

   Shutdown_Socket (Socket);
   Close_Socket (Socket);
   Finalize;

exception when E : others =>
   Put_Line (Exception_Name (E)
             & ": " & Exception_Message (E));
end Daytime_Client;

It appears to connect just fine because if I turn off the server it
gives me:

$ ./daytime_client
GNAT.SOCKETS.SOCKET_ERROR: [111] Connection refused

but if it's on I'm getting the following error:

$ ./daytime_client
ADA.IO_EXCEPTIONS.END_ERROR: s-stratt.adb:188

Also if I change the port to something else open like 22 I get a
segmentation fault:

$ ./daytime_client
Segmentation fault

Why wouldn't it get a similar error if it's only ripping the banner
off of the server port?

Am I doing something wrong with the streams (this is the first time
I've used Ada's streams) or do I need to GNAT.Sockets.Receive_Socket? 
If so can anyone provide me with an example?  I know in C you have to
use a loop, but I didn't know if that was necessary with Ada.Streams. 
I tried it with Receive_Socket also, but I could not figure out how to
print the output to regular stdout....

BTW: I have looked at Samuel Tardieu's AdaSockets but I ran into
compilation problems on Mac 10.2.6 (my home box) so I decided to stick
with GNAT.Sockets since the ultimate goal is to eventually get some
portable socket functions, the first of which I would like to get
similar to a simple Python program:

http://www.qlippoth.com/ripban.py

Any help or guidance would be greatly appreciated.  Thanks!

file13
http://www.qlippoth.com/



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

* Re: GNAT.Sockets Problems
  2003-05-09 19:46 GNAT.Sockets Problems file13
@ 2003-05-11  0:51 ` Craig Carey
  2003-05-12 11:38 ` Simon Clubley
  1 sibling, 0 replies; 3+ messages in thread
From: Craig Carey @ 2003-05-11  0:51 UTC (permalink / raw)




>ADA.IO_EXCEPTIONS.END_ERROR: s-stratt.adb:188

Here is file "s-stratt.adb:188" from the cvs site:

| package body System.Stream_Attributes is     * GNAT of "GCC 3.4" *
|    Err : exception renames Ada.IO_Exceptions.End_Error;
|    ...
|    function I_C (Stream : access RST) return Character is
|       T : S_C;
|       L : SEO;
|    begin
|       Ada.Streams.Read (Stream.all, T, L);
|       if L < T'Last then
L188>      raise Err;
|       else
|          return To_C (T);
|       end if;
|    end I_C;

I doubt that fast Ada programs handle data with a procedure call for each
byte.

I have some personal bindings to GNAT.Sockets here, in file "ptun1.adb":
http://www.ijs.co.nz/code/ada95_http_hdrs.zip (or of a similar name).

------------------------------------
Inset: * Browsing through the abuse officer's censoring proxy *:
 I released a TCP multiplexing proxy named (Ptunnel 2) that allows
 browsing through a censoring proxy. The proxy differs from HTTPort in
 that only 2 log file lines are left behind and it is in Ada and also
 the connections are out to port 80. Port 119 Usenet I/O can be downloaded
 through the proxy, and then all the messages are in a long "stream".
------------------------------------

The I_C() procedure is not something a fast well designed program would
need to contain. Ada's Streams are available and it seems very likely
that only Ada beginners use Streams for efficient code. There were about
passing binary data portably. However maybe outstanding programs convert
variant record data to ASCII text and then compress it. I don't know if
Streams are that essential. One thing that is missing from Ada is an
ability to read from the Standard Input and read directly into an array.

Back to Ada's streams. Strings can be used instead. I do't like I_C():

(1) I_C() reads character by character which is slower than it could be;

(2) I_C() raises exceptions. Some well running TCP programs have the
TCP connect fail often (e.g. 4 times a second). GDB can stop on all of
those exceptions.

Adasocket's TCP connect routine also raises exceptions so the package
is not a solution but it replicates the problem. Here is some of the
Adasockets code (from v1.6):

|   procedure Connect (Socket : in Socket_FD; Host : in String; Port ...
|   ...
|      if C_Connect (Socket.FD, Sin'Address, Sin'Size / 8) = Failure then
|         Current_Errno := Thin.Errno;
|         if Current_Errno = Constants.Econnrefused then
|            raise Connection_Refused;
|         else
|            Raise_With_Message
|              ("Connection failed (errno was" &
|               Integer'Image (Current_Errno) & ')',
|              False);

What would be faster than returning data Character by Character, is to
return the data in a string. Ada's Unbounded Strings is not a serious
option (since I have a faster "Seafood" fast strings package for use
with fast TCP proxies). But few know just how fast the secret Ada
string type is; i.e. the one that passes around strings explaining
exceptions. That unknown string type would be carrying away the Adasockets
error, "Connection failed...".

I had to write a lot of bindings to GNAT.Sockets. 


On 9 May 2003 12:46:48 -0700, file13@qlippoth.zzn.com (file13) wrote:

>Howdy all, I've been tinkering with GNAT.Sockets on Mandrake 9.1 using
>the Gnat-3.15p linux binary and I'm simply trying to write ...
...
>procedure Daytime_Client is
>   Target  : Inet_Addr_Type := Inet_Addr ("127.0.0.1");
>   Socket  : Socket_Type;
>   Server  : Sock_Addr_Type;
>   Channel : Stream_Access;
>begin
>   Initialize;
>   Create_Socket (Socket);
>   Server := (Family_Inet, Target, 13);
>   Connect_Socket (Socket, Server);
>   Channel := Stream (Socket, Server);
>   Put_Line (String'Input (Channel));
>   Shutdown_Socket (Socket);
>   Close_Socket (Socket);
>   Finalize;
...
>$ ./daytime_client
>ADA.IO_EXCEPTIONS.END_ERROR: s-stratt.adb:188
...
>http://www.qlippoth.com/ripban.py [...]
>file13: http://www.qlippoth.com/

Some of that Python code (immediately above) uses Unix signals to timeout
TCP connects. Maybe for Windows, a task would be used instead. Anyway,
signals can cause core dumps. This Python code attempts to kill anything
rather than just one socket:

|        except socket.error:
|            print "Connection refused"
|            sys.exit(1)
|        if os.name == "posix":
|            signal.signal(signal.SIGALRM, alarm_handler)
|            signal.alarm(timeout)
|        banner = sock.recv(1024)

I found that porting TCP code from Windows to Linux, can be slowed a
lot by these issues:
(1) tasks must be carefully unblocked by the program itself, and  Ctrl-C
  SIGTERM, and exit() (GNAT's OS_Exit()) can convert the Linux program
  into a zombie. Badbly designed Ada Linux programs may fail to close.
  It seems to be fixable (despite 1+ GNAT runtime bugs that show up only
  once the program has fully finished).
(2) SO_REUSEADDR needs to be handled correctly (Linux port numbers lock
 up).


Craig Carey








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

* Re: GNAT.Sockets Problems
  2003-05-09 19:46 GNAT.Sockets Problems file13
  2003-05-11  0:51 ` Craig Carey
@ 2003-05-12 11:38 ` Simon Clubley
  1 sibling, 0 replies; 3+ messages in thread
From: Simon Clubley @ 2003-05-12 11:38 UTC (permalink / raw)


In article <28d8936a.0305091146.18a4dd57@posting.google.com>, file13@qlippoth.zzn.com (file13) writes:
> Howdy all, I've been tinkering with GNAT.Sockets on Mandrake 9.1 using
> the Gnat-3.15p linux binary and I'm simply trying to write the first
> day time client from Stevens UNIX Network Programming book with it and
> I can't seem to figure out what I'm doing wrong.
> 
> so far in Ada I have:
> 
> with Ada.Exceptions; use Ada.Exceptions;
> with Ada.Text_IO; use Ada.Text_IO;
> with GNAT.Sockets; use GNAT.Sockets;
> 
> procedure Daytime_Client is
>    Target  : Inet_Addr_Type := Inet_Addr ("127.0.0.1");
>    Socket  : Socket_Type;
>    Server  : Sock_Addr_Type;
>    Channel : Stream_Access;
> begin
>    Initialize;
>    Create_Socket (Socket);
>    Server := (Family_Inet, Target, 13);
> 
>    Connect_Socket (Socket, Server);
> 
>    Channel := Stream (Socket, Server);
>    Put_Line (String'Input (Channel));
               ^^^^^^

That's your problem. 'Input is trying to read the dope information for the
String datatype; so this will never work.

> 
>    Shutdown_Socket (Socket);
>    Close_Socket (Socket);
>    Finalize;
> 
> exception when E : others =>
>    Put_Line (Exception_Name (E)
>              & ": " & Exception_Message (E));
> end Daytime_Client;
> 
> It appears to connect just fine because if I turn off the server it
> gives me:
> 
> $ ./daytime_client
> GNAT.SOCKETS.SOCKET_ERROR: [111] Connection refused
> 
> but if it's on I'm getting the following error:
> 
> $ ./daytime_client
> ADA.IO_EXCEPTIONS.END_ERROR: s-stratt.adb:188
> 
> Also if I change the port to something else open like 22 I get a
> segmentation fault:
> 
> $ ./daytime_client
> Segmentation fault
> 
> Why wouldn't it get a similar error if it's only ripping the banner
> off of the server port?
> 
> Am I doing something wrong with the streams (this is the first time
> I've used Ada's streams) or do I need to GNAT.Sockets.Receive_Socket? 

As it happens, I have also been looking at GNAT.Sockets for the first time
this weekend (and, as a result, Ada.Streams for the first time as well.)

I also tried String'Input before realising why that would not work, and
also got a segmentation fault, presumably because the GNAT runtime is trusting
the information that's it's reading as the dope information, which I found
disappointing as that's the kind of thing that I would expect from C and
not Ada.

> If so can anyone provide me with an example?  I know in C you have to
> use a loop, but I didn't know if that was necessary with Ada.Streams. 
> I tried it with Receive_Socket also, but I could not figure out how to
> print the output to regular stdout....
> 

You could always do a (maybe unchecked) conversion and then treat the
Stream_Elements as a stream of characters. I ended up doing that in order
to get it working with Receive_Socket.

And now for a request of my own:

I have been looking at GNAT.Sockets as part of some investigations into
deciding if my next project will be written in Ada or C. I am finding
GNAT.Sockets to be cumbersome when it comes to reading data, and I am
wondering how others use it.

In case it makes a difference, I am using GNAT.Sockets with GtkAda and am
passing the socket file descriptor to GtkAda so that a callback can be
called when data is available to read, so I must not block in the callback.

Thanks for any information,

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP       
VMS advocate: One who makes a Mac advocate look like a beginner at advocacy.



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

end of thread, other threads:[~2003-05-12 11:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-09 19:46 GNAT.Sockets Problems file13
2003-05-11  0:51 ` Craig Carey
2003-05-12 11:38 ` Simon Clubley

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