digitalmars.D.learn - Buffered Endian Stream Socket?
- Kyle Mallory (25/25) Apr 06 2010 I'm trying to write a series of structs to a stream, which then has to
- Regan Heath (19/50) Apr 21 2010 If you had a BufferedStream wrapping a SocketStream, then I think you
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? Is is possible (or reasonable) to pass in arbitrary structs into EndianStream and expect that it will intelligently convert each type in the struct?
Apr 06 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
Apr 21 2010