Buffered Endian Stream Socket?

Regan Heath regan at netmail.co.nz
Wed Apr 21 04:47:44 PDT 2010


Kyle Mallory wrote:
> I'm trying to write a series of structs to a stream, which then has to 
> be sent over the wire within a single TCP packet, in order for the host, 
> an embedded device, to recognize the message.  If there is too little, 
> or too much data for a given "command" (packet), the device will throw 
> out the entire packet.  Ie, one packet must contain one complete message.
> 
> In all of my messages, the first 23 bytes are a common header.  I'm 
> playing with having this header be a separate struct, apart from the 
> subsequent payload struct.  This will allow me to do simple things like 
> (in pseudo-d-code):
> 
>     msg.foo = 1234;
>     msg.bar = "DMDD";
>     hdr.datalen = Payload.sizeof;
> 
>     packet.write((&hdr)[0..1]);
>     packet.write((&msg)[0..1]);
>     socket.send(packet);
> 
> Since this is network data originating from various platforms, I also 
> need to handle endian issues.
> 
> There are a few problems I'm running into with all of this:
> 
> I can't find a way to load data into a SocketStream without also issuing 
> a Socket.send().  I considered a BufferedStream, or a MemoryStream but 
> its not clear if/or how I would go about issuing an explicate send.  Is 
> there a preferred way to do this that I'm missing?

If you had a BufferedStream wrapping a SocketStream, then I think you 
could call flush(); to trigger the send.  It may depend on the size of 
the BufferedStream..

> Is is possible (or reasonable) to pass in arbitrary structs into 
> EndianStream and expect that it will intelligently convert each type in 
> the struct?

No.. I think you want to create your own PacketStream class containing 
an EndianStream, wrapping a BufferedStream, wrapping a SocketStream.

Then.. all your structs you want to write derive from a common base 
struct and you implement a PacketStream.writeStruct(BaseStruct a) method 
which uses reflection to discover all the members of the struct at runtime.

It would then call itself for all members derived from BaseStruct, and 
EndianStream.write for all basic types.

Alternately, an easier/more verbose way to go is to have a seperate 
writeStruct specifically for each struct you want to write, and manually 
code them up to write all the members.  This way means you have to 
remember to update them as you add members to structs etc.

You'll need a member, or members in PacketStream to start and flush/send 
the packet.  The former would write the packet header to the 
endian/buffer stream and the latter would call flush to send the data.

R


More information about the Digitalmars-d-learn mailing list