【问题标题】:Not multicast packets sent over network returns不是通过网络发送的多播数据包返回
【发布时间】:2016-01-11 19:09:44
【问题描述】:

大家好。

我的软件使用多播组发送消息,但是应用程序充当客户端和服务器,因此它发送 udp 数据包并接收它们。

这是使用包含 2000 个字符的文本进行测试的。

我创建了一个包含 byte[1024] 数组的队列,其中包含需要发送的数据。

问题:

问题在于接收这些多播数据包,在发送的 5 个数据包中,我大多只收到 1 个,经常收到 2 个等等,而且我收到了所有这些数据包的次数很少。

收发结果如下:

  • 已发送数据包:已发送 1、2、3、4、5 个
  • 返回的数据包:1、2、3、4、F(F是序列中的最后一个数据包,即关闭数据包)

12345 134F

12345 1F

12345 134F

12345 14F

12345 1F

12345 1F

12345 1

12345 1

12345 1

12345 1234F

12345 1F

12345 1

12345 1

12345 1

12345 14F

12345 1F

12345 1F

12345 1

12345 1

12345 1

12345 1F

12345 1

发送组播包如下:

        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))
        {
            //handle image and files                
            _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));
            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();

一个线程用于接收数据包并将它们添加到队列中进行处理,第二个线程用于处理。 2个线程的原因可能是接收线程中的处理过多导致了这个“丢包”,但不幸的是它没有解决问题

接收线程:

//initialise multicast group and bind to interface
        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);
        }

【问题讨论】:

  • UDP 是一种尽力而为的协议,没有任何方法可以确保接收到所有段。您应该期望不会收到所有发送的 UDP 段,这在设计时是预先知道的。如果您需要可靠性,请使用 TCP,但您不能使用 TCP 进行多播,因为多播是单向的,而 TCP 需要双向。
  • @RonMaupin 感谢您的回复,您有什么建议可以让我的软件获得最佳性能、减小数据包大小、“双”发送数据包?

标签: c# sockets networking network-programming


【解决方案1】:

有可靠的 UDP 协议和库。我以前使用过 UDT (http://udt.sourceforge.net/),它运行良好。我不知道它的 C# 包装器,但可能有一个或另一个可靠的 UDP C# 实现。

除此之外,还有其他一些建议:

  1. 多播在交换机上主要是个问题。如果可以的话,试着改变它们。有时这也可能是路由器的问题,因此,如果可能,您也可以尝试更改它们。

  2. 尝试发送更少的数据包(或减少发送频率)。如果您的数据包长度低于 1500 字节,那么数据包长度应该不是什么大问题,但是,您也可以尝试减少长度。

  3. 为确保您的代码中没有因某种原因丢失数据包,请使用数据包嗅探器并查看数据包是否真的到达了您的目标计算机。 WireShark 有一个足够好的 GUI,但也有几个基于 GUI 和 CLI 的。

【讨论】:

  • 感谢您的回答。 1.我在路由器上测试这个,实际上是家用路由器。 2. 我坚持使用 1024 字节的多播教程建议,这似乎也太过分了。 3. Wireshark 以我发布的详细形式报告相同的信息。它报告数据包 1、4、5 已发送,其他时候报告数据包 1 已发送。但是,我发送数据包的代码没有问题,因为有时我会收到我发送的所有数据包。为什么会发生这种“损失”?
  • 嗯,就像任何其他数据包一样,它可能由于多种原因而丢失,从一些物理(或多或少短暂的)问题到软件问题。多播增加了必须在路由器和交换机上“克隆”数据包的问题,​​增加了拥塞和可能的缓冲区问题(溢出或其他)。这就是为什么在某种程度上玩时间和消息持续时间可能会有所帮助。说了这么多,您的失败率似乎很高,这就是为什么我认为可能存在硬件问题(也)。
猜你喜欢
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2015-06-29
  • 2017-02-25
  • 2017-11-18
  • 1970-01-01
相关资源
最近更新 更多