Re: recv() sends extra garbage bytes



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

.



Relevant Pages

  • Re: BSD sockets: recv with MSG_WAITALL should return EWOULDBLOCK?
    ... (I am not convinced it is much use for blocking sockets ... many bytes as the size argument to recv() or to close the connection ... And this sounds like 'if you are using a buffer size that doesn't ... Another frame arrives and more data is queued to the socket buffer. ...
    (comp.unix.programmer)
  • Re: TdiBuildReceive question
    ... Irp->IoStatus.Information < the size of the buffer. ... then it is better to fill it as much as possible, and not complete the recv() ... To prevent such a time loss, the TCP protocol has a PSH bit ... PSH means - "the sender does not know when the next bytes will ...
    (microsoft.public.development.device.drivers)
  • Re: recv WSAENOBUFS error
    ... cross-posting, I did cross-post it initially, but I just started using ... it always asks for the "packet length" amount in the call to recv. ... You can set kernel-mode buffer with setsockopt but you'll quickly finish ...
    (microsoft.public.win32.programmer.kernel)
  • Re: recv WSAENOBUFS error
    ... it always asks for the "packet length" amount in the call to recv. ... You can set kernel-mode buffer with setsockopt but you'll quickly finish ... your non-page (kernel) memory if you'll start to do it. ...
    (microsoft.public.win32.programmer.networks)
  • Re: recv WSAENOBUFS error
    ... it always asks for the "packet length" amount in the call to recv. ... You can set kernel-mode buffer with setsockopt but you'll quickly finish ... your non-page (kernel) memory if you'll start to do it. ...
    (microsoft.public.win32.programmer.kernel)