.Net UDP packet loss though all packets arrive (Wireshark) - ReceiveBuffer not the issue

橙三吉。 提交于 2021-02-10 19:44:18

问题


This is the same question as C# UDP packetloss though all packets arrive (WireShark), except I do set ReceiverBuffer to 10MB, and I also monitor Socket.Available which shows the buffer doesn't even reach 200k utilization.

In a simple test case, sending the same small (multicast) UDP packet (net data size: 137) 25,000 times using tcpreplay with at rate of 40Mbps, oftentimes not all packets arrive in my program, although all packets arrive in Wireshark, which I run at the same time on that box. Sometimes it's only one packet that's missing, sometimes it's about a dozen, sometimes more.

The Code

static void Main()
{
    int udpPacketsReceived = 0;
    var bindAddress = IPAddress.Parse("192.168.20.54");
    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    socket.ReceiveBufferSize = 10485760; // 10M

    socket.Bind(new IPEndPoint(bindAddress, 51001));
    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.193.1.1")));
    Console.WriteLine("Effective ReceiveBuffer size: " + socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));

    var t = new Thread(ipAndClient =>
    {
        var buffer = new byte[2000];
        int maxAvail = 0;
        while (true)
        {
            socket.Receive(buffer);
            Interlocked.Increment(ref udpPacketsReceived);
            var available = socket.Available;
            if (available > maxAvail)
            {
                Console.WriteLine("available new max: " + available);
                maxAvail = available;
            }
        }
    });
    t.Start();
    int lastValue = -1;
    while (true)
    {
        var newValue = Thread.VolatileRead(ref udpPacketsReceived);
        if (newValue != lastValue)
        {
            Console.WriteLine("Total UDP packets received: {0}", newValue);
            lastValue = newValue;
        }
        Thread.Sleep(1000);
    }
}

Example output

Effective ReceiveBuffer size: 10485760
Total UDP packets received: 0
available new max: 685
available new max: 3288
available new max: 3836
available new max: 6165
available new max: 8220
available new max: 10960
Total UDP packets received: 14307
available new max: 18632
available new max: 140425
available new max: 141521
available new max: 143439
Total UDP packets received: 24996

What's wrong?

Important addition (which proved crucial in hindsight, see my own answer): I'm running on a Windows guest in a VirtualBox host, using a "bridged" virtual network card.


回答1:


Wireshark gets the packets before they get passed to the protocol stack, while the receive buffer is at the end of the in-kernel protocol stack. There is a lot of memory allocation and other processing going on and on high loads it might simply drop some packets before they reach the receive buffer.

Here's what MS support had to say:

Winsock layer sits on top of the transport layer. Datagrams may be dropped at various layers within the networking stack.




回答2:


Steffen Ullrich's answer and comments lead me to dig deeper into the setup of my system - Windows 8.1 running in a VirtualBox - and I found that for my workloads, which max at around 50Mbps and 20kpps, I could get rid of all packet drops by changing the virtual network card from "bridged" to "Paravirtualized network adapter (virtio-net)".

This necessitates installing network drivers in the Windows guest. Drivers, which can be downloaded via http://www.linux-kvm.org/page/WindowsGuestDrivers/Download_Drivers. The easiest way to get binary, digitally signed drivers is to click the "Fedora" link on that page, and install "netkvm.inf", which is the Red Hat VirtIO Ethernet Adapter driver, for your OS.



来源:https://stackoverflow.com/questions/26540513/net-udp-packet-loss-though-all-packets-arrive-wireshark-receivebuffer-not-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!