views:

102

answers:

2

I want to know the size of the next UDP datagram in the system's queue.

I found this question with a similar doubt, but using boost. The last answer (as of 2010/09/23) say something about using getsockopt with the SO_NREAD option in OS X, but I can't find anything about this with Windows (using Winsock).

Here I found that I can use ioctlsocket with FIONREAD to find out what is the size of the entire queue, but I didn't find anything about the first datagram.

So my question is: Is there a way to determine what is the size of the next UDP datagram in the queue using the sockets API? (I'm not using boost).

I want my code to look like this:

char BigBuffer[ 64 * 1024 ];
void Read( void *Buf, size_t Size ) {
    size_t LengthInQueue = WhatTheSizeOfTheNextDatagram();
    if( Size < LengthInQueue ) {
         recvfrom( Socket, BigBuffer, 64*1024,  /*...*/ );
         memcpy( Buf, BigBuffer, Size );
    }
    else {
         recvfrom( Socket, Buf, size,  /*...*/ );
    }
}

I left out error checking and some parameters for the sake of space and readability. I want to avoid copying to a intermediary buffer when its not needed.

A: 

You can pop this datagram and calculate lenght of this, for get datagram existence information you can use select function, and for get all datagram you can use recv_from function with 64k buffer size agrument, then this function was result what you want.

Svisstack
What do you mean by `pop` ?
Vargas
I think what Svisstack is getting at is something like boost::asio's message_peek ability, this lets you look at data without removing it from the queue. http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/reference/socket_base/message_peek.html Not sure where he is getting the terminology from though.
I can use a `recvfrom` with MSG_PEEK, but it will copy the buffer and then it would need to be copied again to remove it from the queue.
Vargas
+1  A: 

If I understand correctly, you just want to ensure that Buf doesn't overflow, but you don't care about any extra data beyond Size, since you're discarding it anyway. In that case, all you need is this:

recvfrom( Socket, Buf, size,  /*...*/ );

The remainder of the packet is automatically discarded.

Quoted from the docs:

For message-oriented sockets, data is extracted from the first enqueued message, up to the size of the buffer specified. If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost.

casablanca
That would work, but doesn't answer my question...
Vargas
As far as I know, there isn't a direct way to do this. I guess the rationale behind this is that UDP packets are usually of a fixed length specified by the protocol.
casablanca