digitalmars.D.learn - Sending a struct over TCP
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: .. void write(T)(T input) { buf ~= *(cast(ubyte[T.sizeof]*)&input)[0 .. T.sizeof]; } Then I send the ubyte[] over through TCP via a SocketStream. On the client-side I read and convert the ubyte[] back to the struct: uint len = ss.read(buffer); auto mem = new mem_stream(buffer[0 .. len]); data d = mem.read!(data); writefln("[id:%d] len=%d, data=%s (%d)", d.id, len, d.content, d.content.sizeof); Which outputs: [id:100] len=12, data= (8) The read function: .. int pos = 0; .. T read(T)() { T output = *(cast(T*)(buf[pos .. pos + T.sizeof].ptr)); pos += T.sizeof; return output; } The Integer got sent perfectly (and i does the same with additional ulongs etc.) but the char[] did not, though, it is still the same size. So why can't I send the char[]? is it because it is a array of pointers to the address-space of the server? Thank you in advance :) (Btw. My files are also attatched)
Mar 06 2007
Reply to SirErugor,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: .. void write(T)(T input) { buf ~= *(cast(ubyte[T.sizeof]*)&input)[0 .. T.sizeof]; } Then I send the ubyte[] over through TCP via a SocketStream. On the client-side I read and convert the ubyte[] back to the struct: uint len = ss.read(buffer); auto mem = new mem_stream(buffer[0 .. len]); data d = mem.read!(data); writefln("[id:%d] len=%d, data=%s (%d)", d.id, len, d.content, d.content.sizeof); Which outputs: [id:100] len=12, data= (8) The read function: .. int pos = 0; .. T read(T)() { T output = *(cast(T*)(buf[pos .. pos + T.sizeof].ptr)); pos += T.sizeof; return output; } The Integer got sent perfectly (and i does the same with additional ulongs etc.) but the char[] did not, though, it is still the same size. So why can't I send the char[]? is it because it is a array of pointers to the address-space of the server? Thank you in advance :) (Btw. My files are also attatched)char[] is by reference. under the hood it is a pointer/length pair. Somewhere I have a code generator that tries to make this work.
Mar 06 2007
Reply to Benjamin,Reply to SirErugor,ftp://ftp.novell.uidaho.edu/public_html/netidl_0_12_sdk.zip somewhere in there is a template that will suck up arrays (and arrays of arrays, ...) and let you send them over the wire. try running the program on a file like this interface foo { void bar(char[] i); void big(char[][] i); } I haven't looked at it for ages so I won't make any claims about how well it will work.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: .. void write(T)(T input) { buf ~= *(cast(ubyte[T.sizeof]*)&input)[0 .. T.sizeof]; } Then I send the ubyte[] over through TCP via a SocketStream. On the client-side I read and convert the ubyte[] back to the struct: uint len = ss.read(buffer); auto mem = new mem_stream(buffer[0 .. len]); data d = mem.read!(data); writefln("[id:%d] len=%d, data=%s (%d)", d.id, len, d.content, d.content.sizeof); Which outputs: [id:100] len=12, data= (8) The read function: .. int pos = 0; .. T read(T)() { T output = *(cast(T*)(buf[pos .. pos + T.sizeof].ptr)); pos += T.sizeof; return output; } The Integer got sent perfectly (and i does the same with additional ulongs etc.) but the char[] did not, though, it is still the same size. So why can't I send the char[]? is it because it is a array of pointers to the address-space of the server? Thank you in advance :) (Btw. My files are also attatched)char[] is by reference. under the hood it is a pointer/length pair. Somewhere I have a code generator that tries to make this work.
Mar 06 2007
BCS Wrote:Reply to Benjamin, ftp://ftp.novell.uidaho.edu/public_html/netidl_0_12_sdk.zip somewhere in there is a template that will suck up arrays (and arrays of arrays, ...) and let you send them over the wire. try running the program on a file like this interface foo { void bar(char[] i); void big(char[][] i); } I haven't looked at it for ages so I won't make any claims about how well it will work.Thanks BCS, But I cannot access the file? Not even as anonymous. Could you please either post the file here or send it to my email? :-) Cheers!
Mar 08 2007
Reply to SirErugor,BCS Wrote:Damb stupid firefox. No, wait, That was my bad. <g> http://www.uidaho.edu/~shro8822/netidl_0_12_sdk.zip That should work.Reply to Benjamin, ftp://ftp.novell.uidaho.edu/public_html/netidl_0_12_sdk.zip somewhere in there is a template that will suck up arrays (and arrays of arrays, ...) and let you send them over the wire. try running the program on a file like this interface foo { void bar(char[] i); void big(char[][] i); } I haven't looked at it for ages so I won't make any claims about how well it will work.Thanks BCS, But I cannot access the file? Not even as anonymous. Could you please either post the file here or send it to my email? :-) Cheers!
Mar 08 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
Mar 08 2007
Downs Wrote: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 --downsThank you very much, Downs! This works perfectly and I've gotten quite a better understanding on templates as well. Cheers! :)
Mar 09 2007
SirErugor wrote:Thank you very much, Downs! This works perfectly and I've gotten quite a better understanding on templates as well. Cheers! :)Glad to be of service :D
Mar 09 2007