Re: recv() sends extra garbage bytes
- From: "David Schwartz" <davids@xxxxxxxxxxxxx>
- Date: 27 Mar 2007 18:29:40 -0700
On Mar 27, 10:41 am, chsal...@xxxxxxxxx wrote:
David, are you suggesting something more like this:
/* Read 4 bytes to obtain size of recv'd data */
do {
switch (buffer.recv(new_socket, sizeof(uint32_t))) {
case -1: return SOCKET_ERR;
case 0: return CLOSE_SOCKET;
default: break;
}
} while (buffer.used_bytes < sizeof(uint32_t));
memcpy(&recv_size, buffer.data, sizeof(uint32_t));
uint32_t remaining = recv_size - sizeof(uint32_t);
uint32_t next;
do {
switch (next = buffer.recv(new_socket, remaining)) {
case -1: return SOCKET_ERR;
case 0: return CLOSE_SOCKET;
default: break;
}
remaining -= next;
} while (buffer.used_bytes < recv_size);
This is how I originally coded it. This way, I only recv() the amount
of bytes that I expect should be remaining. This seems to be what
you're saying to do. But this brings me back to my original
question. All the literature on recv() never indicates you should do
this. And others here have indicated that recv() will never actually
recv() more than was sent. So even if I do something like:
buffer.recv(new_sock, 10000000);
...I'll still only recv the amount that was sent. So I shouldn't need
to keep subtracting the amount received in each iteration from the
value I pass to recv().
This is not a particularly good solution either. There are two
problems, one in complexity and one in performance. In complexity, it
requires two loops, one to get all the length bytes and one to get all
the data. In performance, it will require at least two call to recv
even if all the data is there.
The basic outline of a textbook solution is this:
1) Call 'recv' passing it however much buffer space you have left.
2) If you do not have enough data to know how many bytes you need, go
to step 1.
3) Compute how many bytes you need. If you don't have that many, go to
step 1.
4) Process the bytes you have received.
5) If you do not have any leftover bytes, empty the buffer and go to
step 1.
6) If you have leftover bytes, arrange things so the buffer only has
the leftover and go to step 2.
In pseudo code, assuming the packet length encoded in the data
includes the four bytes for the length.
int packet_len(unsigned char *buf_ptr)
{ /* unpack length of packet */
int ret=buf_ptr[0];
ret<=8; ret|=buf_ptr[1];
ret<=8; ret|=buf_ptr[2];
ret<=8; ret|=buf_ptr[3];
return ret;
}
int i, buf_ptr=0, packet_len;
unsigned char buf[BUF_SIZE];
/* This takes the packet without the length header */
extern void ProcessPacket(unsigned char *data, int length);
while(1)
{
i=recv(socket, buf+buf_ptr, BUF_SIZE-buf_ptr);
if(i<=0) return; /* error/eof */
buf_ptr+=i;
while( (buf_ptr>=4) &&
(buf_ptr>=(packet_len=get_len(buf))) )
{
ProcessPacket(buf+4, packet_len-4);
if(packet_len==buf_ptr) buf_ptr=0;
else
{ /* save leftover */
memmove(buf, buf+buf_ptr, buf_ptr-packet_len);
buf_ptr-=packet_len;
}
}
}
Hope that helps.
DS
.
- References:
- recv() sends extra garbage bytes
- From: chsalvia
- Re: recv() sends extra garbage bytes
- From: Frank Cusack
- Re: recv() sends extra garbage bytes
- From: chsalvia
- Re: recv() sends extra garbage bytes
- From: David Schwartz
- Re: recv() sends extra garbage bytes
- From: chsalvia
- recv() sends extra garbage bytes
- Prev by Date: Re: poll() revents variable
- Next by Date: Re: char *** help
- Previous by thread: Re: recv() sends extra garbage bytes
- Next by thread: Re: recv() sends extra garbage bytes
- Index(es):
Relevant Pages
|