In standard socket programming, the 'recv()' function is used to obtain data from a stream. With TCP/IP, a result of recv'ing the packet is that the TCP/IP connection window size increases, allowing more data to be sent. On embedded devices this style of programming can be harmful. Using recv with the MSG_PEEK flag should leave the data in the input buffer, which I assume means that the TCP window remains the same size. You would of course have to remember to recv again without the peek flag when your processing is done.
- When creating proxies, or protocol translators, this style of programming can defeat the flow control mechanisms inherent in TCP/IP. More data should only be allowed once the proxy has finished dealing with the packet. Allowing more data after starting to process a packet can lead to congestion on the device if other packets arrive. By allowing more data only when the packet has been fully dealt with, end-to-end flow control through proxies is automatic and not a special mechanism that has to be programmed by the developer.
- Every recv() results in data being copied from the internal buffer to your buffer. If you are now forwarding this data, possibly modified to another interface, you must copy it again with a send(). That's two copies where none were actually required, resulting in a slower embedded device.
- The number of bytes returned by an recv() cannot be predicted. This typically leads to a style of coding where a larger buffer is provided, just in case, and much of it not used. To avoid allocating them up front you could malloc and free the buffers as needed, but why add such code and then worry about possible memory leaks if the data can instead be read in place via a pointer? It is possible to ascertain the number of bytes currently in the buffer using an ioctl (ioctlsocket in the winsock abomination). The actual recv() call doesn't have to return this number of bytes, but you can recv in a loop until the buffer is full.
recv() makes socket code more messy than it could be. An alternative interface that allows you to decouple the copying and the flow control mechanism from reading the incoming stream can lead to better code.
What's an acceptable alternative to recv() in this context?
Use something other than the low-level Berkeley C socket libraries.
POSIX Async IO should be able to use user-provided input/output buffers for zero-copy I/O (although, implementations might just map AIO over the berkeley interfaces anyway...)
Hmm, I thought this page might be about how it is relatively simple to write the rest of the letters in the word "receive". ... But then you wouldn't be able to smugly align you recv and send calls!
CategoryConsideredHarmful