From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on ip-172-31-65-14.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 Path: eternal-september.org!reader01.eternal-september.org!aioe.org!XkhLYGh9FeaGRJtDGav81g.user.46.165.242.75.POSTED!not-for-mail From: Simon Wright Newsgroups: comp.lang.ada Subject: Re: Sockets, Streams, and Element_Arrays: Much confusion Date: Sat, 31 Dec 2022 17:39:07 +0000 Organization: Aioe.org NNTP Server Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: gioia.aioe.org; logging-data="21867"; posting-host="XkhLYGh9FeaGRJtDGav81g.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org"; User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.1 (darwin) X-Notice: Filtered by postfilter v. 0.9.2 Cancel-Lock: sha1:i87oQ+/9NyEicLxUa2LcUHKDrLU= Xref: reader01.eternal-september.org comp.lang.ada:64753 List-Id: Mark Gardner writes: > GNAT.Sockets gives me a Stream_Element_Array, which I can't find any > documentation on how to make use of other than "You should also be > able to get a Stream, which you should use instead" (About ten years > ago, on this very newsgroup, somebody said not to use streams with > UDP, or at least not GNAT.Sockets.Stream). The reasoning behind the recommendation not to use streams with UDP was as follows (there's a faint possibility that it no longer applies!) If the data type you want to send is e.g. type Message is record Id : Integer; Val : Boolean; end record; and you create a datagram socket and from that a stream, then use Message'Write to the stream, GNAT will transmit each component of Message separately in canonical order (the order they're written in the type declaration). This results in two datagrams being sent, one of 4 bytes and one of 1 byte. If you take the same approach at the destination, Message'Read reads one datagram of 4 bytes, and one of 1 byte, and it all looks perfect from the outside. If the destination is expecting a 5 byte record, of course, things won't work so well. The approach we adopted was to create a 'memory stream', which is a chunk of memory that you can treat as a stream (see for example ColdFrame.Memory_Streams at [1]). With Ada2022, you should be able to use Ada.Streams.Storage.Bounded[2]. Message'Write the record into the memory stream; transmit the written contents as one datagram. To read, create a memory stream large enough for the message you expect; read a datagram into the memory stream; Message'Read (Stream => the_memory_stream, Item => a_message); You can use gnatbind's switch -xdr to "Use the target-independent XDR protocol for stream oriented attributes instead of the default implementation which is based on direct binary representations and is therefore target-and endianness-dependent". [1] https://github.com/simonjwright/coldframe/blob/master/lib/coldframe-memory_streams.ads [2] http://www.ada-auth.org/standards/22rm/html/RM-13-13-1.html#p25