+2  A: 

For streaming protocols such as TCP, you can pretty much set your buffer to any size. That said, common values that are powers of 2 such as 4096 or 8192 are recommended.

If there is more data then what your buffer, it will simply be saved in the kernel for your next call to recv.

Yes, you can keep growing your buffer. You can do a recv into the middle of the buffer starting at offset idx, you would do:

recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
R Samuel Klatchko
Power of two can be more efficient in multiple ways, and is strongly suggested.
Yann Ramin
vicatcu
+3  A: 

If you have a SOCK_STREAM socket, recv just gets "up to the first 3000 bytes" from the stream. There is no clear guidance on how big to make the buffer: the only time you know how big a stream is, is when it's all done;-).

If you have a SOCK_DGRAM socket, and the datagram is larger than the buffer, recv fills the buffer with the first part of the datagram, returns -1, and sets errno to EMSGSIZE. Unfortunately, if the protocol is UDP, this means the rest of the datagram is lost -- part of why UDP is called an unreliable protocol (I know that there are reliable datagram protocols but they aren't very popular -- I couldn't name one in the TCP/IP family, despite knowing the latter pretty well;-).

To grow a buffer dynamically, allocate it initially with malloc and use realloc as needed. But that won't help you with recv from a UDP source, alas.

Alex Martelli
A: 

16kb is about right; if you're using gigabit ethernet, each packet could be 9kb in size.

Andrew McGregor
+4  A: 

The answers to these questions vary depending on whether you are using a stream socket (SOCK_STREAM) or a datagram socket (SOCK_DGRAM) - within TCP/IP, the former corresponds to TCP and the latter to UDP.

How do you know how big to make the buffer passed to recv()?

  • SOCK_STREAM: It doesn't really matter - just pick a size (3000 is fine). Larger buffers will be more efficient if you're transferring large amounts of data.

  • SOCK_DGRAM: Use a buffer large enough to hold the biggest packet that your application-level protocol ever sends. If you're using UDP, then in general your application-level protocol shouldn't be sending packets larger than about 1400 bytes, because they'll ceratinly need to be fragmented and reassembled.

What happens if recv gets a packet larger than the buffer?

  • SOCK_STREAM: The question doesn't really make sense as put, because stream sockets don't have a concept of packets - they're just a continuous stream of bytes. If there's more bytes available to read than your buffer has room for, then they'll be queued by the OS and available for your next call to recv.

  • SOCK_DGRAM: The excess bytes are discarded.

How can I know if I have received the entire message?

  • SOCK_STREAM: You need to build some way of determining the end-of-message into your application-level protocol. Commonly this is either a length prefix (starting each message with the length of the message) or an end-of-message delimiter (which might just be a newline in a text-based protocol, for example).

  • SOCK_DGRAM: An single recv call always returns a single datagram.

Is there a way I can make a buffer not have a fixed amount of space, so that I can keep adding to it without fear of running out of space?

No. However, you can try to resize the buffer using realloc() (if it was originally allocated with malloc() or calloc(), that is).

caf
Thanks, that's exactly the type of response I was looking for. Very helpful.
Silmaril89
I have an "/r/n/r/n" at the end of a message in the protocol I'm using. And I have a do while loop, inside I'm calling recv I place the message at the beginning of recv_buffer. and my while statement looks like this while((!(strstr(recv_buffer, "\r\n\r\n")); My question is, is it possible for one recv to get "\r\n" and in the next recv get "\r\n", so that my while condition never comes true?
Silmaril89
Yes, it is. You can solve that problem by looping around if you don't have a complete message and stuffing the bytes from the next `recv` into the buffer following the partial message. You shouldn't use `strstr()` on the raw buffer filled by `recv()` - there's no guarantee that it contains a nul-terminator, so it might cause `strstr()` to crash.
caf
A: 

There are no absolute answer to your question because technology always bound to implementation-specific. I am assuming you are communicating in UDP because incoming buffer size does not bring problem to TCP communication.

According to RFC 768, the packet size (header inclusive) for UDP can range from 8 to 65 515 bytes. So the fail-proof size for incoming buffer will be 65 507bytes (~64KB)

However, not all large packet can be properly routed by network devices, refer to existing discussion for more information:

What is the optimal size of a UDP packet for maximum throughput?
What is the largest Safe UDP Packet Size on the Internet

YeenFei