www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Receiving data into a type using sockets

reply Jonathan Sternberg <jonathansternberg gmail.com> writes:
I'm trying to learn how to do some networking code in D. In C, if I wanted to
read 4 bytes into an integer, I could just do (ignoring any error detection):

int foo;
recv(sockfd, &foo, sizeof(int), 0);

How do I do this with D? The receive function takes in a void [] parameter and
doesn't take in a number of bytes to read. Is there anyway to accomplish this
in D?
Jun 05 2011
parent reply David Nadlinger <see klickverbot.at> writes:
On 6/5/11 8:51 PM, Jonathan Sternberg wrote:
 I'm trying to learn how to do some networking code in D. In C, if I wanted to
 read 4 bytes into an integer, I could just do (ignoring any error detection):

 int foo;
 recv(sockfd,&foo, sizeof(int), 0);

 How do I do this with D? The receive function takes in a void [] parameter and
 doesn't take in a number of bytes to read. Is there anyway to accomplish this
 in D?

auto socket = new Socket(…); … int foo; socket.receive((&foo)[0..1]); --- void[] is like an array of bytes, with the difference to ubyte[] being that it can contain pointers which must be taken into account by the GC, and implicit convertibility. However, all the socket functions should operate on ubyte[] instead of void[] by current guidelines – the socket module is really old, this will definitely be changed when it will be overhauled/replaced. David
Jun 05 2011
next sibling parent reply Jonathan Sternberg <jonathansternberg gmail.com> writes:
Cool. It compiles, but it doesn't seem to be doing exactly what I want. Say I
send
2 integers from the server to the client. When I do this on the client, it seems
to do the wrong thing.

int first, second;
auto sock = new TcpSocket();
sock.connect(new InternetAddress("localhost", 10000));

writeln( sock.receive((&first)[0..int.sizeof]) );
writeln( sock.receive((&second)[0..int.sizeof] );

This seems to print 8 and then block on the second call to receive. I thought
that
D was supposed to recognize that the array was only 4 bytes long and read only
that much. (note: on a 32-bit machine, so int comes out to 4 bytes)

When I do:

writeln( (&first)[0..int.sizeof].length );

It prints 4 as it's supposed to.
Jun 05 2011
parent David Nadlinger <see klickverbot.at> writes:
On 6/5/11 9:49 PM, Jonathan Sternberg wrote:
 Cool. It compiles, but it doesn't seem to be doing exactly what I want. Say I
send
 2 integers from the server to the client. When I do this on the client, it
seems
 to do the wrong thing.

 int first, second;
 auto sock = new TcpSocket();
 sock.connect(new InternetAddress("localhost", 10000));

 writeln( sock.receive((&first)[0..int.sizeof]) );
 writeln( sock.receive((&second)[0..int.sizeof] );

 This seems to print 8 and then block on the second call to receive. I thought
that
 D was supposed to recognize that the array was only 4 bytes long and read only
 that much. (note: on a 32-bit machine, so int comes out to 4 bytes)

 When I do:

 writeln( (&first)[0..int.sizeof].length );

 It prints 4 as it's supposed to.

&first is of type int*, so (&first)[0..int.sizeof] returns a slice pointing to int.sizeof (i.e. 4) ints, not a single one as you intend to. Just use »(&first)[0..1]« as per my original reply, and you should be fine. David
Jun 05 2011
prev sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--001636c5c006685bd004a4fc91b7
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

On Sun, Jun 5, 2011 at 12:55 PM, David Nadlinger <see klickverbot.at> wrote=
:

 On 6/5/11 9:49 PM, Jonathan Sternberg wrote:

 Cool. It compiles, but it doesn't seem to be doing exactly what I want.
 Say I send
 2 integers from the server to the client. When I do this on the client, =


 seems
 to do the wrong thing.

 int first, second;
 auto sock =3D new TcpSocket();
 sock.connect(new InternetAddress("localhost", 10000));

 writeln( sock.receive((&first)[0..int.sizeof]) );
 writeln( sock.receive((&second)[0..int.sizeof] );

 This seems to print 8 and then block on the second call to receive. I
 thought that
 D was supposed to recognize that the array was only 4 bytes long and rea=


 only
 that much. (note: on a 32-bit machine, so int comes out to 4 bytes)

 When I do:

 writeln( (&first)[0..int.sizeof].length );

 It prints 4 as it's supposed to.

&first is of type int*, so (&first)[0..int.sizeof] returns a slice pointi=

 to int.sizeof (i.e. 4) ints, not a single one as you intend to. Just use
 =BB(&first)[0..1]=AB as per my original reply, and you should be fine.

Also, note that receive is basically a direct call to C's receive, which means that it has the same behavior with regards to buffer filling. Calling sock.receive((&first)[0..1]) returns the number of bytes read, which may be less than 4. I've handled this in the past by writing a template function that takes a primitive type and loops until it has read all the bytes it needs. Oh, and D's int is always 32 bits, on 32 bit or 64 bit platforms. size_t is an alias that switches from uint on 32 bit to ulong on 64 bit, and there's another alias somewhere for signed types (ssize_t, I believe). The primitiv= e types always have the same sizes until you get into things like cent. --001636c5c006685bd004a4fc91b7 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Sun, Jun 5, 2011 at 12:55 PM, David Nadlinger= <span dir=3D"ltr">&lt;<a href=3D"mailto:see klickverbot.at">see klickverbo= t.at</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"ma= rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div><div></div><div class=3D"h5">On 6/5/11 9:49 PM, Jonathan Sternberg wro= te:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Cool. It compiles, but it doesn&#39;t seem to be doing exactly what I want.= Say I send<br> 2 integers from the server to the client. When I do this on the client, it = seems<br> to do the wrong thing.<br> <br> int first, second;<br> auto sock =3D new TcpSocket();<br> sock.connect(new InternetAddress(&quot;localhost&quot;, 10000));<br> <br> writeln( sock.receive((&amp;first)[0..int.sizeof]) );<br> writeln( sock.receive((&amp;second)[0..int.sizeof] );<br> <br> This seems to print 8 and then block on the second call to receive. I thoug= ht that<br> D was supposed to recognize that the array was only 4 bytes long and read o= nly<br> that much. (note: on a 32-bit machine, so int comes out to 4 bytes)<br> <br> When I do:<br> <br> writeln( (&amp;first)[0..int.sizeof].length );<br> <br> It prints 4 as it&#39;s supposed to.<br> </blockquote> <br></div></div> &amp;first is of type int*, so (&amp;first)[0..int.sizeof] returns a slice = pointing to int.sizeof (i.e. 4) ints, not a single one as you intend to. Ju= st use =BB(&amp;first)[0..1]=AB as per my original reply, and you should be= fine.<br> </blockquote><div><br></div><div>Also, note that receive is basically a dir= ect call to C&#39;s receive, which means that it has the same behavior with= regards to buffer filling. Calling sock.receive((&amp;first)[0..1]) return= s the number of bytes read, which may be less than 4. I&#39;ve handled this= in the past by writing a template function that takes a primitive type and= loops until it has read all the bytes it needs.</div> <div>Oh, and D&#39;s int is always 32 bits, on 32 bit or 64 bit platforms. = size_t is an alias that switches from uint on 32 bit to ulong on 64 bit, an= d there&#39;s another alias somewhere for signed types (ssize_t, I believe)= . The primitive types always have the same sizes until you get into things = like cent.</div> </div><br> --001636c5c006685bd004a4fc91b7--
Jun 05 2011