I have written an application in C# that receives UDP packets continuously streamed from an electronic device.
The electronic device is connected directly to a PC running the application, and there are no switches or others network device connected.
I imagine that the network infrastructure of the PC is as follows:
- The network interface (network card) receives the data and process them up to the transport layer, puts packets in a buffer and sends an interrupt to the OS.
- The OS handles the interrupt at some point, and empties the buffer of the network interface (i.e. all packets in the buffer are emptied.)
- The OS signals the .NET framework that data is available.
- My program picks up the packets and process them.
Now, as I use UDP, I would expect to see packet loss and duplicates, etc. and I do. The drop out seem to occur whenever the PC does something else (I remote control the PC using remote desktop over a second network interface in the PC).
Can I be certain that if the packets have been received by the OS that they will get passed on to my application? (Intuitively I think; yes, because the OS will use RAM as a buffer so there will be plenty of space.)
If so, I suspect that the OS grabs all packets from the network interface that may have gathered since the network interface raised the interrupt, and puts them in the RAM. If this is true, then does .NET iterate through each of these packets invoking the callbacks in .NET and my program associated with 开发者_如何学编程a packet being received?
Intuitively I would also blame the network interface for packet loss due to its buffer overflowing before the OS can empty it. Is this correct?
I also suspect that packet sniffers also receive the data AFTER the OS received it, and so the data received by the packet sniffer and the data received by my program should be identical.
I have written a test-program that streams 1 kB UDP data to my own network interface at a rate of 1000 Hz. The program also receives the data, and checks to see whether the data has been received in order. (The packets contain a packet number). I can conclude that they are received out of order, and that more are received out of order whenever the computer is doing something else. (I didn't expect this behavior, so I didn't write a routine to check for lost packets. I will do this tomorrow.)
To finalize. How can I reduce the packet loss? Is it a good idea to create a buffer in C#, or can I rely on the OS to have a buffer? Can I setup the buffer size of the OS? Can I setup the buffer size of the network interface?
Thanks.
A lot of questions, let me answer what I can (in no particular order)
The larger the packet, the higher chance of fragmentation, the higher the number of fragments. In theory, if you lose a fragment, you've lost the packet (the underlying layers can't reassemble the packet, and therefore it's dropped)
A number of sources suggest UDP packets to be around 576 bytes (see http://www.faqs.org/rfcs/rfc791.html) to ensure fragmentation never occurs.
There is a fairly large buffer in the OS (4M by default if my memory is correct), but it's at the kernel level and not easily viewed. However, you can adjust the ReceiveBufferSize in the Socket class to expand this value. If you are on a 32-bit machine, I would keep that value no higher than 8M, for 64bit you can go somewhat higher, I think for our application we went to 64M.
UDP does not give you any packet ordering whatsoever, if you need ordered packets you are immediately back in TCP-land (or writing UDP apps that basically implement TCP/IP, which causes you to lose the value of UDP)
Make sure that your calls to BeginReceive are handled Asynchronously, even if you are just dumping them into a buffer internally. If you are handling them synchronously, you will lose data if your receive code handles them at a slower rate than they are coming in, at least eventually.
Lastly, while sometimes tweaking the network interface will help (badly configured driver settings, for example) generally you are going to find that it's at least as challenged as your network hardware itself, which means that most tweaks you do there are negated by network issues upstream.
精彩评论