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 --downs
Thank 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









BCS <ao pathlink.com> 