我正在调试一个奇怪的问题,发生在实时环境中的一台机器上 .

我的应用程序(从属)应该在任何时候从LAN中的另一台主机(主机)接收UDP多播消息,但显然它只在从机先前已发送消息时才这样做 .

我的期望是:

  • Slave要求提供数据

  • Master发送数据

  • 奴隶接收和消费

  • 师父等2-3分钟

  • Master发送新数据

  • Slave接收并使用新数据

  • 重复步骤4到6

我看到的是:

  • 奴隶没有收到任何东西

但是,如果我让奴隶连续要求新数据(轮询,即重复步骤1),我终于得到了消息 .

我在Wireshark中看到来自主服务器的消息确实是由从属主机接收的 . 只是我的应用程序没有收到它 . 更令人惊讶的是,在相同网络上运行的另一个主从对,使用相同的应用程序,工作正常,以及我在测试环境中的配对 .

slave应用程序在异步模式下使用 UdpClient . 以下是监听器的初始化方式:

private void ListenMain()
{
    try
    {
        UdpClient udpClient = new UdpClient();
        udpClient.Client.ExclusiveAddressUse = false;
        udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000);
        IPv4InterfaceProperties p = adapter.GetIPProperties().GetIPv4Properties();

        udpClient.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(p.Index));

        udpClient.Client.Bind(endPoint);
        udpClient.JoinMulticastGroup(12345);

        ListenState listenState = new ListenState();
        listenState.udpClient = udpClient;
        listenStates.Add(listenState);
        logger.Debug("Waiting for messages");
        udpClient.BeginReceive(new AsyncCallback(OnPacketReceived), listenState);
    }
    catch (Exception e)
    {
        logger.Error(e, "ListenMain() encountered an error");
    }
}

这是收到的数据包的处理程序:

private void OnPacketReceived(IAsyncResult result)
{
    logger.Trace("OnPacketReceived");
    IPEndPoint recvAddress = new IPEndPoint(IPAddress.Any, MULTICAST_PORT);
    ListenState state = result.AsyncState as ListenState;
    byte[] receive_byte_array;
    try
    {
        logger.Trace("before EndReceive");
        receive_byte_array = state.udpClient.EndReceive(result, ref recvAddress);
        logger.Trace("after EndReceive, got {0} bytes", receive_byte_array.Length);

        // packet handling goes here...

        // do the loop
        logger.Trace("waiting for another packet");
        state.udpClient.BeginReceive(new AsyncCallback(OnPacketReceived), state);
    }
    catch (ObjectDisposedException)
    {
        logger.Info("Socket is now closed");
        return;
    }
    catch (Exception e)
    {
        logger.Warn(e, "exception in handling incoming message");
    }
}

当然,轮询新数据不是最佳解决方案,并且会引入不必要的延迟 . 我想知道哪个现象会导致UdpClient丢失传入的数据包,除非之前有相同的UdpClient发送了一些内容 .