Sending a struct over TCP

Downs default_357-line at yahoo.de
Thu Mar 8 04:29:16 PST 2007


SirErugor wrote:
> Hi there,
> 
> I've set up a server and a client application and I want to be able to send a struct with fx. an integer and a char[]. So first I convert it to a ubyte[] like this:
> 

This is rather easy to achieve with templates
I needed to do something similar a bit back, so here's the code I used:

template isArray(T) { const isArray=false; }
template isArray(T: T[]) { const isArray=true; }

/// serialize
void ser(T)(T value, void delegate(char[]) dg) {
   static if (isArray!(T)) {
     /// First dump the length (as uint, so it's fixed across platforms), then the data
     /// \todo special case for char[] arrays
     ser!(uint)(value.length, dg);
     foreach (element; value) ser(element, dg);
   } else {
     static if (is(T==struct)) {
       /// Just serialize the elements in order
       foreach (element; value.tupleof) ser(element, dg);
     } else {
       dg((cast(char*)&value)[0..value.sizeof]);
     }
   }
}

void ser(T, dummy=void)(T value, inout char[] target) {
   ser!(T)(value, (char[] c) { target~=c; });
}

char[] splinter(inout char[] c, size_t amount) {
   assert(c.length!<amount);
   auto res=c[0..amount];
   c=c[amount..$];
   return res;
}

T carve(T)(inout char[] t) {
   T result;
   static if (isArray!(T)) {
     result.length=carve!(uint)(t);
     foreach (inout elem; result) elem=carve!(typeof(result[0]))(t);
   } else {
     static if (is(T==struct)) {
       foreach (idx, bogus; result.tupleof)
         result.tupleof[idx]=carve!(typeof(bogus))(t);
     } else {
       result=*(cast(T*)(splinter(t, T.sizeof).ptr));
     }
   }
   return result;
}


Use it like

struct test {
   int e;
   char[] f;
}
char[] send; test t;
ser(t, (char[] c) { send~=c; });
/* Now send "send" over the socket .. at the other end: */
char[] received; test t=carve!(test)(received);

Greetings  --downs


More information about the Digitalmars-d-learn mailing list