Re: Linux equivalent for ioctlsocket(FIONREAD) on datagram sockets



On Mar 9, 6:17 pm, already5cho...@xxxxxxxxx wrote:

Now you are trying to be constructive.

You simply don't like the answer.

However your concentration on the letter of standard prevents you from
understanding the spirit.
Yes, UDP is defined us unreliable. But it also defined as "best
effort". It would be practically useless without the later.

Right, but everything is designed based on the premise that it is
unreliable. You cannot *ever* assume it is reliable.

Now imagine the IP stack the adheres to both the letter and the spirit
of the standard. Imagine fast CPU/Memory/IO bus. Imagine slow physical
line. Please take into account that for modern CPUs/memory/IO-Bus even
1GBe is a "slow line". Imagine that fast CPU sends a burst of UDP
datagrams which is longer than SEND_BUFFER through blocking socket.

That would be a bug. The sending application is responsible for
transmit pacing in a UDP application.

Now what the IP stack/packet driver that adheres to the "best effort"
spirit of UDP standard should do in that particular case? Drop the
packet? No way, that's against the spirit. The correct way would be
blocking a clling thread until the NIC hardware (probably through DMA)
reads one or more packets from socket's send buffer freeing up space
for the next one. Comprende?

Right, but you can't design based on that. The exact same problem can
happen one hop away on the other side of a router. So what point is
there in going to special effort to solve this one case when it leaves
another version of the exact same problem unsolved?

With UDP, you need a general solution to bottlenecks that can occur
anywhere. There is little point to special solutions to special
bottlenecks, unless you have some special way to know that that's the
only problem you are going to have.

The APIs and interfaces are designed for the general case.

What is the best way to receive fast UDP stream (order of 20K to 50K
packets per second) while dropping as few packets as possible?

Obviously, it depends on the operating system.

On Windows the [pseudo]code presented in my original post easily
achieves packet error rate of ~1E-7 but hits the wall when we try to
do better. And on Windows when you hit the wall.... well, you hit the
wall.

On Windows, posting lots of overlapped I/O requests and using a pool
of threads is the best you can do.

On Linux (Ubuntu 8.10 x64) so far I see packet error rates in excess
of 1E-5. And yes, I tried both blocking and non-blocking sockets. Non-
blocking variant significantly reduces the CPU load but, at least on
fast computers, makes no material difference to the error rates. The
fact that the my current Linux results are so horribly bad leaves the
hope that I am doing something wrong... May be, I should try scatter-
gather read? Or something else?

Set the receive queue as large as you can. Keep a thread blocked on
'recvmsg'. Make sure that this thread does as little work as possible
before it gets back to 'recvmsg'. Keep your own internal queue of
received datagrams.

Keep a pool of free memory chunks so you don't block in the normal
allocator. Pre-allocate, say, 1,000 packet buffers with the necessary
space to form them into a linked list. Your loop looks like this:

1) Receive a UDP packet into my pre-allocated buffer.
2) Add it to my own linked list of packets.
3) Try to acquire the lock on the master linked list of packets. If
fewer than 10 packets received, do so non-blocking. If more than 10,
do so blocking.
4) If we failed to acquire the lock, jump to step 1.
5) Add our linked list of packets to the end of the system's linked
list.
6) Release the lock.
7) Go to step 1.

Keep all memory allocation out of the fast path. Do not block on the
linked list that is shared with other threads unless too much data has
backed up.

Note that you basically cannot do this with a single thread. There are
simply too many ways you can unexpectedly block.

I understand that quite a few people would try to suggest that I
shouldn't want :( to receive UDP datagrams at low error rate. All
these people are welcome to say it right here but sincerely I don't
promise a polite response.

It's definitely bad to allow your code to introduce extra packet loss.
You should definitely do your best to avoid losing data that has gone
to all the trouble to get to your system.

DS
.



Relevant Pages

  • Re: UPD better than TCP in streaming video/audio ?
    ... > UDP gains speed over TCP because it carries no information that would ... it doesn't even know that packets were lost. ... which is perfect for UDP. ... > Finally, there's the possibility of multicast data - for instance, a live ...
    (microsoft.public.win32.programmer.networks)
  • Re: NTP and Firewall help needed.
    ... >>port 123 for udp and tcp. ... The action here is applied for packets that fall off ... > - ACCEPT any and all traffic coming from the localhost interface ...
    (comp.os.linux.setup)
  • Re: Possible bug in .Net 2.0 udp sockets?
    ... You won't miss any UDP packets with a buffer that large! ... R> I called BeginReceiveFrom() several times on purpose, ... If you don't do that, indeed, UDP stack can drop packets. ... it stores it in the queue. ...
    (microsoft.public.dotnet.framework)
  • Re: Update: UDP 770 Potential Worm
    ... > the network immediately after the 'attack', ... were no packets indicating some form of replication. ... I noticed that the UDP ... > of the UDP datagrams is the IP address of the proxy? ...
    (Incidents)
  • Re: UDP vs TCP
    ... I understand that UDP doesn't guarantee proper delivery of the message, that's why we have to add the CRC to the message to check if the message received is correct. ... TCP for instance will break up a large packet into smaller ... > into the packets and then the receiving app would have to read ...
    (microsoft.public.vb.enterprise)

Quantcast