Thread overview |
---|
March 06, 2007 Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Attachments: | 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) |
March 06, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to SirErugor | 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.
|
March 06, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | Reply to Benjamin, > 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. > 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. |
March 08, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to SirErugor | 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 |
March 08, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | 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!
|
March 08, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to SirErugor | Reply to SirErugor, > 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! > Damb stupid firefox. No, wait, That was my bad. <g> http://www.uidaho.edu/~shro8822/netidl_0_12_sdk.zip That should work. |
March 09, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to Downs | 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 --downs
Thank you very much, Downs!
This works perfectly and I've gotten quite a better understanding on templates as well.
Cheers! :)
|
March 09, 2007 Re: Sending a struct over TCP | ||||
---|---|---|---|---|
| ||||
Posted in reply to SirErugor | 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
|
Copyright © 1999-2021 by the D Language Foundation