.Net UDP数据包丢失虽然所有数据包都到了(Wireshark) - ReceiveBuffer不是问题

时间:2014-10-24 02:21:19

标签: .net sockets networking udp

这是与C# UDP packetloss though all packets arrive (WireShark)相同的问题,除了我将ReceiverBuffer设置为10MB,我还监控Socket.Available,显示缓冲区甚至达不到200k利用率。

在一个简单的测试案例中,使用tcpreplay以40Mbps的速率发送相同的小(多播)UDP数据包(净数据大小:137)25,000次,通常不是所有数据包都到达我的程序,尽管所有数据包都到达Wireshark ,我在那个盒子上同时跑。有时它只丢失了一个数据包,有时它只有十几个,有时甚至更多。

守则

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);
    }
}

示例输出

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

出了什么问题?

重要添加(事后证明这一点至关重要,请参阅my own answer):我使用&#34在VirtualBox主机中的Windows来宾上运行桥连#34;虚拟网卡

2 个答案:

答案 0 :(得分:1)

Wireshark在数据包传递到协议堆栈之前获取数据包,而接收缓冲区则在内核协议堆栈的末尾。有很多内存分配和其他处理在高负载上进行,它可能只是在一些数据包到达接收缓冲区之前丢弃它们。

以下是MS support had to say

  

Winsock图层位于传输层的顶部。可以在网络堆栈中的各个层丢弃数据报。

答案 1 :(得分:0)

Steffen Ullrich的回答和评论让我深入研究了我的系统设置 - 在VirtualBox中运行的Windows 8.1 - 我发现对于我的工作负载,最高可达50Mbps和20kpps,我可以摆脱通过将虚拟网卡从“桥接”更改为“Paravirtualized network adapter (virtio-net)来丢弃所有数据包丢失。

这需要在Windows guest虚拟机中安装网络驱动程序。驱动程序,可以通过http://www.linux-kvm.org/page/WindowsGuestDrivers/Download_Drivers下载。获取二进制数字签名驱动程序的最简单方法是单击该页面上的“Fedora”链接,然后安装“netkvm.inf”,即 Red Hat VirtIO以太网适配器驱动程序,适用于您的操作系统。

相关问题