From: Adrien Plisson <aplisson-news@stochastique.net>
Subject: Re: Sending Variable Length Messages with GNAT.Sockets
Date: Mon, 09 May 2005 20:49:56 +0200
Date: 2005-05-09T20:49:56+02:00 [thread overview]
Message-ID: <427fb046$0$1421$ba620e4c@news.skynet.be> (raw)
In-Reply-To: <1115650283.330746.109740@f14g2000cwb.googlegroups.com>
markp wrote:
> Thanks John.
>
> I still have a fundamental problem. I am working on legacy code in
> which data is defined in records (or arrays of records) which are sent
> in variable lengths. We use address, byte count to send the exact
> number of bytes. Using Streams, it seems they type has to be of
> Stream_element_Array. The only way I can see to send/receive these
> "variable" messages is to first read our message header which contains
> the number of bytes in the message. Then, create a Stream_Element_Array
> of the exact size for the next read. Then, do an unchecked conversion
> or a copy bytes routine to get the data into my data type for
> processing. Does this sound correct?
this sounds bof bof... a bit complicated...
since you seem still struggling on this, here is some help, based on
wild guesses i made given your previous posts:
with Ada.Text_IO,
Ada.Streams,
Ada.Streams.Stream_IO;
procedure Main is
-- let's assume you have this kind of records
type Data_Record is record
Some : Integer;
Dummy : String (1..8);
Fields : Float;
end record;
-- according to the description you gave in a previous post,
-- your message type is implemented (simplified) this way
type Data_Record_Array is array (1..512) of Data_Record;
type Message is record
-- the message header (very simplified)
-- holds the number of actual records in the data
Number_Of_Records : Natural;
-- the message data
Data : Data_Record_Array;
end record;
-- declaration of the custom stream attribute procedures
procedure Message_Read( Stream : access
Ada.Streams.Root_Stream_Type'Class; Msg : out Message );
for Message'Read use Message_Read;
procedure Message_Write( Stream : access
Ada.Streams.Root_Stream_Type'Class; Msg : in Message );
for Message'Write use Message_Write;
-- implementation of Message'Read
procedure Message_Read( Stream : access
Ada.Streams.Root_Stream_Type'Class; Msg : out Message ) is
Size : Natural;
begin
-- first read the header
-- WARNING: on the network, the size is in bytes,
-- not in number of records
Natural'Read( Stream, Size );
Msg.Number_Of_Records := Size / (Data_Record'Size /
Ada.Streams.Stream_Element'Size);
-- then read the data
for I in Msg.Data'First..Msg.Data'First + Msg.Number_Of_Records
- 1 loop
Data_Record'Read( Stream, Msg.Data(I) );
end loop;
end Message_Read;
-- implementation of Message'Write
procedure Message_Write( Stream : access
Ada.Streams.Root_Stream_Type'Class; Msg : in Message ) is
begin
-- first write the header
-- WARNING: on the network, the size is in bytes,
-- not in number of records
Natural'Write( Stream, Msg.Number_Of_Records * Data_Record'Size
/ Ada.Streams.Stream_Element'Size );
-- then write the data
for I in Msg.Data'First..Msg.Data'First + Msg.Number_Of_Records
- 1 loop
Data_Record'Write( Stream, Msg.Data(I) );
end loop;
end Message_Write;
-- this is for to simplify test writing
use Ada.Streams.Stream_IO;
begin
-- since socket streams and file streams are identical (really, all
streams work the same)
-- we will use files for testing
-- first write some stuffs to a stream
declare
F : File_Type;
S : Stream_Access;
M : Message;
begin
-- create a new file
Create( F, Out_File, "test.out" );
-- get the stream corresponding to the file
S := Stream( F );
-- create 5 messages
for I in 1..5 loop
-- fill each message with dummy data
M.Number_Of_Records := I * 2;
for J in 1..M.Number_Of_Records loop
M.Data(J) := Data_Record'(Some => J, Dummy =>
"20050509", Fields => 42.0 / Float( I ) + Float( J ));
end loop;
-- write the data to the stream
Message'Write( S, M );
end loop;
-- close the file
Close( F );
end;
-- here you can look at "test.out" and see what it contains.
-- now read some stuffs from the stream
declare
F : File_Type;
S : Stream_Access;
M : Message;
begin
-- open the file
Open( F, In_File, "test.out" );
-- get the stream corresponding to the file
S := Stream( F );
-- read all messages on the stream
loop
Message'Read( S, M );
-- display the content of the messages
Ada.Text_IO.Put_Line( "Message found : " & Natural'Image(
M.Number_Of_Records ) & " records =>" );
for I in M.Data'First..M.Data'First + M.Number_Of_Records -
1 loop
Ada.Text_IO.Put_Line( " " & Integer'Image(
M.Data(I).Some ) & " " & M.Data(I).Dummy & " " & Float'Image(
M.Data(I).Fields ) );
end loop;
end loop;
exception
when End_Error =>
-- when there are no more messages in the stream file,
-- close it
Close( F );
end;
end Main;
--
rien
next prev parent reply other threads:[~2005-05-09 18:49 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-09 10:11 Sending Variable Length Messages with GNAT.Sockets markp
2005-05-09 10:39 ` Adrien Plisson
2005-05-09 11:19 ` markp
2005-05-09 11:50 ` Adrien Plisson
2005-05-09 14:30 ` John B. Matthews
2005-05-09 14:51 ` markp
2005-05-09 18:49 ` Adrien Plisson [this message]
2005-05-09 19:16 ` Simon Wright
2005-05-10 15:08 ` markp
2005-05-10 20:34 ` Simon Wright
2005-05-11 13:19 ` Marc A. Criley
2005-05-11 17:14 ` tmoran
2005-05-11 21:05 ` Simon Wright
2005-05-12 10:24 ` Jacob Sparre Andersen
2005-05-14 11:12 ` Simon Wright
2005-05-09 11:19 ` Jeff C
2005-05-09 11:35 ` markp
2005-05-09 11:57 ` Adrien Plisson
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox