🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Asynchronous socket...

Started by
5 comments, last by emzee 22 years, 9 months ago
I red that tutorial by Drew Sikora, but there is one problem. How do i recv() whole data when i dont know the size of it? Is there a way how i could get the size of data waiting to be recv()''d? 4llj00rb4ndw1th4r3b3l0ngst0m3p0rn
4llj00rb4ndw1th4r3b3l0ngst0m3p0rn
Advertisement
Typically, you just create a buffer large enough to receive the data you want. Another option is to stick a 2 byte header at the front of your data packets to signify the length. You only do this if you need discreet message sizes for TCP/IP (which is a stream oriented protocol by nature.)

There are ways to "peek" at the message before removing it from the transport buffer but I''d highly discourage that as it can hurt performance (among other issues).

All you need to do:

1. Create a buffer of 10,000 bytes (or whatever).
2. Call recv() passing the buffer you created.
3. Use the buffer. recv() returns how many bytes where received.

You could even make your own NetBuffer class that maintains an internal buffer and a pointer into that buffer. If using C++ you could overload operator char* to return the a pointer into the buffer. This pointer could be the start of the buffer or a pointer to the end of the last received data (i.e. append).




Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
Dire.Wolf is mostly correct... however, the usual way to determine whether or not you are done reading from the buffer is to loop through recv() calls until it returns a 0. That means there is no more data to be read from the socket.
Pyabo is mistaken.

When you call recv() on a TCP socket and it returns 0, the socket connection has been closed. It does not signify that you have no more data to receive!




Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
I totally agree with Wolf. The way I learned to do this at work was to have a header on each "packet" which tells the recieving method how large the data is, then you pull that sized chunk of data from the socket.
but isnt it that send() would wait untill it has recv()d data what is large as i given in recv()''s 3. param?
4llj00rb4ndw1th4r3b3l0ngst0m3p0rn
No. When you call recv() on a socket set to blocking mode , recv() will not return until the transport provider receives some data. You never really know how much data you are going to receive. What you do know is that Winsock will not overflow your buffer (which is why you pass in the buffer len to recv()). When recv() returns it returns the number of bytes it has copied into your buffer.

The same is true with send() and TCP/IP. When you call send() on a socket set to blocking mode , send() will block until it sends some data. With TCP/IP send() does not guarantee that it will send all the data you passed to it. You need to check send()''s return value, which is the number of bytes sent, and compare it to the length of the data you wanted sent. If the bytes sent is less than the buffer length, you need to call send() again passing a pointer to the data plus the number of bytes sent (pointer arithmetic).

Example:

  // data and datalen declared somewhere elseint bytes_total = 0,    bytes_sent = 0;while(bytes_total < datalen){    bytes_sent = send(socket,                       data + bytes_total,                       datalen - bytes_total,                       0);    if(bytes_sent == 0)    {        // connection has been closed    }    else if(bytes_sent == SOCKET_ERROR)    {        // and error occurred while calling send().    }        bytes_total += bytes_sent;}  


A similiar approach can be used for receiving data.

  int bytes_total = 0,      bytes_requested = 100, // receive ATLEAST 100 bytes    bytes_recv = 0; while(bytes_total < bytes_requested){    bytes_recv = recv(socket,                       data + bytes_total,                      datalen - bytes_total,                      0);    if(bytes_recv == 0)    {        // connection has been closed    }    else if(bytes_recv == SOCKET_ERROR)    {        // and error occurred while calling send().    }        bytes_total += bytes_recv;}  


Hope this answers your question.

Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com

This topic is closed to new replies.

Advertisement