views:

89

answers:

3

Hi, In some cases, I'd like to explicitly discard packets waiting on the socket with as little overhead as possible. It seems there's no explicit "drop udp buffer" system call, but maybe I'm wrong?

The next best way would be probably to recv the packet to a temporary buffer and just drop it. It seems I can't receive 0 bytes, since man says about recv: The return value will be 0 when the peer has performed an orderly shutdown. So 1 is the minimum in this case.

Is there any other way to handle this?

Just in case - this is not a premature optimisation. The only thing this server is doing is forwarding / dispatching the UDP packets in a specific way - although recv with len=1 won't kill me, I'd rather just discard the whole queue in one go with some more specific function (hopefully lowering the latency).

+3  A: 

I'd rather just discard the whole queue in one go

Since this is UDP we are talking here: close(udp_server_socket) and socket()/bind() again?

To my understanding should work.

Dummy00001
That's an interesting solution... unfortunately that won't work for privileged range after a dropping root (if the socket was bound before). I'll try though.
viraptor
Ah - and it will cause errors to be returned to the client - which I can't accept unfortunately...
viraptor
@viraptor: "it will cause errors to be returned to the client" - only if client runs locally. And clients should ignore errors from UDP anyway (beside probably bumping an error counter) as the communication type isn't reliable anyway. Otherwise, personally I see no problem is simply reading out all the messages: UDP recv buffer by default is small enough and even if you bump it to few megs, it still peanuts for modern CPUs.
Dummy00001
It's for voip clients which I have no control over. They might decide to close the connection if I start returning ICMP errors for each packet for a longer time - so can't risk that. As I said - it's not slow to read them, but poll / read is the only thing this program does, so if I can make this quicker, I want to try...
viraptor
A: 

man says about recv: the return value will be 0 when the peer has performed an orderly shutdown.

That doesn't apply to UDP. There is no "connection" to shut down in UDP. A return value of 0 is perfectly valid, it just means datagram with no payload was received (i.e. the IP and UDP headers only.)

Not sure that helps your problem or not. I really don't understand where you are going with the len=1 stuff.

Duck
Not completely true. You can call connect on a UDP socket which will cause it to reject packets from any other host:port combo and will enable delivery of ICMP network errors to the socket.
Robert S. Barnes
Connect != connection though. There is no handshake, no tear down, no ordering of packets, or anything most people commonly associate with a connection. To my mind connect is a misnomer with UDP and leads to confusion.
Duck
I would disagree and say that it's just as much of a connection as `TCP`. Remember that even in `TCP` each end maintains it's own independent state and if one end crashes the other will never know about it until they do two sends and get a broken pipe error. The concept of "connection" in my mind relates to the issue of whether you're talking many-to-one or one-to-one in a way that's enforced. Of course there are arguments to see it either way :-)
Robert S. Barnes
re. `len=1` - I just tried to receive the minimum size I could, so that I don't have to allocate a proper buffer / copy 1k packet, when I actually want to drop it afterwards. I wasn't sure if `len=0` (or exactly: `recv(fd, NULL, 0, 0)`) is safe to use on every system.
viraptor
@Robert -- connect(2) on a UDP socket just causes it to set the default destination for write(2)/send(2); it does NOT cause it to reject packets from other sources.
Chris Dodd
@Chris Dodd: You're mistaken. Read this: http://kerneltrap.com/node/7491
Robert S. Barnes
+4  A: 

You can have the kernel discard your UDP packets by setting the UDP receive buffer to 0.

int UdpBufSize = 0;
socklen_t optlen = sizeof(UdpBufSize);
setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &UdpBufSize, optlen);

Whenever you see fit to receive packets, you can then set the buffer to, for example, 4096 bytes.

WindsurferOak
It's `)
viraptor
Thanks for the catch! :)
WindsurferOak