TCP Socket between Ada and Python

Viewed 256

I'm really new to Ada and would like to create a TCP socket between Ada and Python. The Ada programm should act as server and the Python program as client. The main use case is to receive string commands from Python and confirm their execution. Without the Ada.Streams.Write(Channel.All, Data); in the Ada Server and the data = s.recv(512) it is at least possible to receive a Hello World from the Python Client. I would like to send an answer from the Ada server to the Python client, that's the point where I stuck. I get an "Socket Error Connection Timed Out". Ada Server:

   use GNAT.Sockets;
   Server : Socket_Type;
   Socket : Socket_Type;
   Address : Sock_Addr_Type;
   Channel : Stream_Access;
   Data : Stream_Element_Array(1 .. 512);
   Last : Stream_Element_Offset;
   S : Unbounded_String;
begin
   Put_Line("Server Config Started..");
   Create_Socket(Server);
   Set_Socket_Option(Server,
                     Socket_Level,
                     (Reuse_Address, True));
   Set_Socket_Option(Server, Socket_Level,(Receive_Timeout, Timeout => 5.0));
   Bind_Socket(Server, Address => (Family => Family_Inet, Addr => Inet_Addr("127.0.0.2"), Port => 65432));
   Listen_Socket(Server);
   Accept_Socket(Server, Socket, Address);
   Put_Line("Client connected from:" & Image(Address));
   Channel := Stream(Socket);
   Ada.Streams.Read(Channel.All, Data, Last);
   Put_Line("Received:");
   for I in 1 .. Last loop
      Put(Character'Val(Data(I)));
   end loop;
   Ada.Streams.Write(Channel.All, Data);

Python Client:

HOST = '127.0.0.2'  
PORT = 65432        

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'Hello, world')
    data = s.recv(512)

What am I doing wrong? Has someone a hint? Thanks in advance.

1 Answers

The reason things don’t go the way you hoped is that you’ve put the Receive_Timeout socket option on the Server socket; you need to put it on Socket instead, since that’s the socket you’re receiving from.

As things stand: the call

Ada.Streams.Read(Channel.All, Data, Last);

will terminate either when it has read Data’Length (512) bytes or when the other end closes the socket.

Before you included the data = s.recv(512) at the end of the Python script, the Python was closing the socket.

Now, it’s waiting for the Ada side to send it 512 bytes back - and the Ada side is waiting for the Python side to send it the remaining (512 - 12) bytes. Classic deadly embrace.

How to fix? possibly, have the Ada side read character-by-character until it reads a terminator (e.g. \0). Or you could use datagrams. In any case, you need a protocol to determine message boundaries on the wire.


On macOS, the Ada side prints out the message it has received as soon as the Python side sends it. This is not what the man page for setsockopt() says re: SO_RCVTIMEO! It should wait for the timeout set (5 seconds) before deciding to give up.

Related