Question

Basically, I managed to connect several clients to a single server, but I have a problem reading from the server. I have two tasks (threads): one for reading, and one for writing.

  1. The offset never gets to 0 resulting an infinite loop. How can I print "Incoming > " every time there is a new incoming message from server?
  2. And Im not really sure about the buffer size. I tried 1..1024 but nothing get printed until server sends 1024 chars.
  3. is String'Write a shortcut for ada.streams.write?

Writing data

String'Write(channel, "Hello client");
--Where channel is Gnat.Sockets.Stream_Access type

Reading data from server

    task body reader_task is    
      Offset : Streams.Stream_Element_Count;
      Buffer : Streams.Stream_Element_Array (1 .. 1);
   begin
     loop
      Text_IO.put_line("Incoming > "); 
      loop
          Streams.Read (Channel.All, Buffer, Offset);
      exit when offset = 0; 
          for I in Buffer'Range loop
              Text_IO.Put (Character'Val (Buffer (I)));
          end loop;
      end loop;
     end loop;
   end reader_task; 
Was it helpful?

Solution 2

GNAT sockets are created blocking, so when you call Streams.Read it will read from the socket until

  1. your Buffer is full; or
  2. there aren’t yet any more bytes to read; or
  3. the socket has been closed.

In case 2, the Read call blocks until more data arrives. Only in case 3 will you get back an underfull buffer (in your code, Offset less than Buffer’Last).

If you have multiple clients, any of which could be sending data, you can use GNAT.Sockets.Check_Selector to block until one of the client sockets has data to read, and then read from that socket.

As for reading a complete input message, you can read a byte at a time until you reach a terminator (in the case of an HTTP request, that would be a double CR/LF). Of course, you need to agree with the client side what will constitute a terminator.

The answer from @ajb has covered writing.

OTHER TIPS

To answer the last question: String'Write uses Ada.Streams.Write (more accurately, since Ada.Streams.Write operates on an abstract type and is dispatching, it will call whatever overriding Write has been written for the actual stream type). But it's not a shorthand. Ada.Streams.Write takes an array of Stream_Element as its parameter (Stream_Element is probably a byte). But String'Write takes a String, which is an array of characters, not an array of stream elements. The implementation treats the String as an array of stream elements and writes each one. In effect, it will write each character, so the result is very similar, but the constructs are not identical. Things like Integer'Write will treat an integer as an array of stream elements and call Ada.Streams.Write on it; how the implementation does that is not defined.

'Write can also be used on user-defined types. There are default rules for how this works, but you can also write your own 'Write routine to use instead of the default. RM 13.13.2 explains all of this.

(The first two questions seem to be about whether Read is blocking or non-blocking for a GNAT socket. I don't know the answer to that.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top