【发布时间】:2015-10-22 08:10:14
【问题描述】:
我正在调试一个奇怪的问题,发生在实时环境中的一台机器上。
我的应用程序(从属)应该随时从 LAN 中的另一台主机(主控)接收 UDP 多播消息,但显然它只有在从属之前发送过消息时才会这样做。
我的预期是:
- 从站请求数据
- Master 发送数据
- Slave 接收和消费
- Master 等待 2-3 分钟
- Master 发送新数据
- Slave 接收并消费新数据
- 重复从 4 到 6 的步骤
我看到的是:
- 从站没有收到任何东西
但是如果我让从站不断地请求新数据(轮询,即重复第 1 步),我终于得到了消息。
我在 Wireshark 中看到来自 master 的消息确实被 slave host 接收到了。只是我的应用程序没有收到它。更令人惊讶的是,在同一网络上运行相同应用程序的另一主从对运行良好,以及我在测试环境中的一对。
从属应用在异步模式下使用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 之前发送过东西。
【问题讨论】:
-
一个疯狂的猜测,但它可能与
ExclusiveAddressUse和ReuseAddress有关吗?尝试反转这些值,看看是否可行。 -
我会尝试删除套接字选项。你在使用超时吗?我认为它不会影响异步接收,但如果它影响它可能是原因。
-
我试图删除所有套接字选项,但应用程序仍然没有收到数据包...
-
记录器中的输出给了你什么?
-
(state.udpClient.BeginReceive 可能直接在同一个线程中返回,如果数据立即可用)
标签: c# network-programming multicast udpclient