C#-发送5个多播UDP数据包可能导致3个或更多数据包丢失

本文关键字:数据包 3个 多数据 5个 发送 多播 UDP C#- | 更新日期: 2023-09-27 18:29:48

所有

通过局域网发送多播数据包是否可能导致部分或至少50%的数据包丢失。

我的应用程序使用多播数据包,当发送这些数据包时,有时我只收到1个,其他时候收到2个。我只收到了两次我发送的所有数据包。

以下是我所做的测试,以查看哪些数据包被返回/接收。发送了5个数据包,但并非全部返回(F-发送数据包序列中的最后一个数据包)

2000个随机字符用于这些测试。

1234514F

12345134F

123451F

123451

123451

123451F

12345134F

我总是收到至少一包。我理解多播=UDP,但丢失这么多数据包似乎并不正常。

发送多播数据包:

        Socket _listener_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        foreach (IPAddress localIP in Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
        {                
            _listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_MultiIP, localIP));
            _listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 1);
            _listener_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            _listener_socket.MulticastLoopback = true;
            _listener_socket.Connect(new IPEndPoint(_MultiIP, _PORT));
            int count = MSGS_TO_SEND.Count;
            while (count > 0)
            {                    
                count--;
                byte[] temp = (byte[])(MSGS_TO_SEND.Dequeue());
                _listener_socket.Send(temp, _BYTE_BUFFER_SIZE, SocketFlags.None);
                MSGS_TO_SEND.Enqueue(temp);
            }
        }
        _listener_socket.Close();

和接收:

        Socket _sender_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _PORT);
        _sender_socket.Bind(ipep);
        IPAddress localip = _MultiIP;
        _sender_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(localip, IPAddress.Any));
        Q_RECIEVE = new Queue<char[]>();
        while (_sender_socket.IsBound && !bStop)
        {
            byte[] b = new byte[_BYTE_BUFFER_SIZE];
            _sender_socket.Receive(b);
            char[] chars = new char[_BYTE_BUFFER_SIZE];
            System.Buffer.BlockCopy(b, 0, chars, 0, b.Length);
            Q_RECIEVE.Enqueue(chars);
        }

更新

一些有趣的结果-工藤感谢赛斯的建议

在测试了防火墙建议后,我收到了一些改进,但仍有数据包丢失:

我禁用了我的卡巴斯基防火墙,恢复到Windows 10 Defender防火墙:

12345234英尺

12345234英尺

123451234 f

123451F

1234514F

12345234英尺

123451

123451

12345234英尺

禁用卡巴斯基防火墙后,我将字节[]大小从1024更改为512,因此每个数据包只发送256个字符(线程睡眠时间为20ms),结果显著改善:

1234567892345678F

1234567892345678F

1234567892345678F

1234567892345678F

1234567892345678F

只有我的第一个包裹被丢弃了,但这是一个很大的进步!

C#-发送5个多播UDP数据包可能导致3个或更多数据包丢失

是的,任何时候发送UDP都有多种因素会导致数据包丢失,即使是在LAN上。以下是一些似乎相关的内容:

  • 2000字节比典型的LAN MTU 1500(更少的报头)大。这意味着数据报将被分段。如果丢失了任何片段,整个数据报就会丢失,如果片段以特定模式到达,一些防火墙就会阻止它们
  • UDP本身没有流量控制。如果你发送的数据太多、太快,数据包就会被丢弃。听起来你一次只发送几个数据报,但要检查你的UDP发送和接收缓冲区。如果其中一个数据报的大小仅足以容纳一个或两个数据报,则其余数据报可能会被丢弃
  • 防火墙有时会奇怪地处理UDP。DoS预防、深度数据包检查、隧道阻塞和一堆听起来很安全的流行语意味着防火墙对数据报的目的进行了疯狂的猜测。如果防火墙猜测错误,您的一些数据报可能会被丢弃
  • 看起来您正在将TTL设置为1。理论上,这对于局域网来说是正确的。但如果本地路由有点偏离,可能会导致一些数据包被丢弃

因此,将有效负载减少到1400字节,确保UDP发送和接收缓冲区至少为64千字节(最好是一兆字节,没有理由吝啬),禁用任何防火墙,并使用更大的TTL进行测试。

如果其中任何一个解决了问题,你可以深入研究,找出确切的原因。