5
int recvfrom(SOCKET            socket, 
             char            * buffer, 
             int               buflen, 
             int               flags, 
             struct sockaddr * from, 
             int             * fromlen);

I know that recvfrom() returns immediately after it reads buflen from socket. My questions here are -

  1. What if i have requested buflen of 2000 and a single packet in the socket queue is of size 2400?

  2. What if i have requested buflen of 2000 and a single packet in the socket queue is of size 1400?

  3. Are the answers for above questions apply same for both TCP and UDP? If not, whats the difference.

Appreciate the reply in advance.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
pa1
  • 778
  • 3
  • 11
  • 26

2 Answers2

5

First, recvfrom() only returns immediately if there is already something waiting to be read, or if the socket is in non-blocking mode. Otherwise, it waits for data to arrive.

Second, UDP is all-or-nothing. Unlike TCP, which operates on streaming data, UDP operates in datagrams instead, and datagrams cannot be read in pieces.

So, to answer your questions:

  1. 2000 bytes will be copied into your buffer, the remaining 400 bytes are discarded and lost, because your buffer is too small to receive the full datagram. recvfrom() will report an EMSGSIZE error.

  2. your buffer is large enough to receive the full datagram, so 1400 bytes will be copied into your buffer. recvfrom() will report success.

  3. These do not apply the same to TCP. First, you don't typically use recvfrom() with TCP, you use recv() instead. But in either case, in TCP, recv/from() receives whatever bytes are currently available at that moment, blocking if needed, up to the specified number of bytes but may be less. You can keep calling recv/from() to receive the remaining bytes, as TCP is stream-based. Since UDP is message-based, you cannot receive the remaining bytes, they are lost. The next recv/from() will read the next available datagram.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • reply to the first answer, by truncated you mean i will be able to get the residual bytes by the next recvfrom call? – pa1 Oct 11 '15 at 19:02
  • 1
    @Coder you will lost the rest. Just use 64k buffer for UDP. – Stas Oct 11 '15 at 19:05
  • 1
    @Coder: in TCP, yes. In UDP, no. – Remy Lebeau Oct 11 '15 at 19:06
  • @Coder: to elaborate on Stas' comment, 64k is the largest size for a UDP datagram, so if you use a 64k buffer for reading then you will never truncate datagrams. – Remy Lebeau Oct 11 '15 at 19:10
  • Thanks for the number, any source for the same? – pa1 Oct 11 '15 at 19:13
  • @RemyLebeau : Reply for your first answer - "recvfrom() will report an EMSGSIZE error." It will read 2000 bytes and rest 400 bytes will be lost i hear. By this i can assume that call is success, so when will EMSGSIZE error come into picture here? – pa1 Oct 11 '15 at 19:19
  • 1
    @Coder: A UDP packet header uses a 16bit unsigned integer for the payload size, so `recvfrom()` can never read more than 65535 bytes at a time in UDP. – Remy Lebeau Oct 11 '15 at 19:19
  • @Coder: EMSGSIZE is not success. Data was lost. `recvfrom()` will fill your buffer with 2000 bytes and then exit with an EMSGSIZE error code to tell you what happened. You have to look at the error and decide whether you want to process those 2000 bytes or ignore them since the message is incomplete. This depends on the particular protocol you are implementing, whether loss of data is acceptable or not. – Remy Lebeau Oct 11 '15 at 19:23
  • @Remy one more query, what if I don't receive any packets at all at clients side, all the packets will be queued? Is there a limit to this? If yes, how can I read this. – pa1 Oct 12 '15 at 03:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92083/discussion-between-remy-lebeau-and-coder). – Remy Lebeau Oct 12 '15 at 20:55
  • `EMSGSIZE` is the other error that is set by `send` function when a packet doesn't fit in the link MTU. `recv` doesn't return this error, it just discard excess bytes – ZAB Jun 21 '22 at 13:20
2

recvfrom() reads up to buflen from the socket. It can read less, which is why you should always check the return value.

1) It will copy 2000 bytes into your buffer. For UDP the excess data will be lost. For TCP you should be able to receive it with another call to recvfrom().

2) It will copy 1400 bytes into your buffer.

3) Generally recvfrom() is used for UDP, recv() is for TCP, but otherwise the behaviour is the same as above.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Colin
  • 3,394
  • 1
  • 21
  • 29
  • You mean to say, recvfrom returns as soon as it hits either requested buf or size of a single packet first? – pa1 Oct 11 '15 at 18:59
  • recvfrom returns as soon as there is something to return. Whether you use TCP or UDP determines how much it returns and whether data loss can occur orr not. – Remy Lebeau Oct 11 '15 at 19:01
  • It will read as much data as is currently available, up to the size of the buffer. Not necessarily the size of a single packet. – Colin Oct 11 '15 at 19:03
  • 2
    @Coder for UDP, recvfrom gives you 1 packet (that might be truncated if your buffer is too small, and the remaining data of that packet is lost forever). It does not combine the result of several packets. For TCP it's different as TCP is a stream, and packet boundaries are not preserved - and you get as much data, up to your buffer size, once any data is received. – nos Oct 11 '15 at 19:05
  • @Colin__s i don't understand, isn't your comment contradictory to the 2) answer you gave? Let me expand 2 question a bit more, say i have 2 packets in queue of 1400 bytes each and i have requested 2000,as per your comment a single recvfrom call will return 2000 bytes(?) 1400 first packet + 600 of next packet? – pa1 Oct 11 '15 at 19:08
  • That's correct, sorry if my comment was not clear. By up to the size of the buffer I mean that that's the maximum, but not necessarily how much you will get. – Colin Oct 11 '15 at 19:10
  • @Coder: In UDP, each call to `recvfrom` reads 1 and only 1 packet. If you request 2000 and multiple packets are in the queue and the next available packet is 1400, you will only get 1400, not 2000. Call `recvfrom()` again to read the next available 1400 packet. – Remy Lebeau Oct 11 '15 at 19:13