I'm debugging a strange problem, happening on one of the machines in the live environment.
My app (slave) is supposed to be receiving UDP multicast messages at any time from another host (master) in the LAN, but apparently it does so only if the slave has previously sent a message.
What I expected is:
- Slave asks for data
- Master sends the data
- Slave receives and consumes
- Master waits 2-3 minutes
- Master sends new data
- Slave receives and consumes the new data
- Steps from 4 to 6 are repeated
What I see is:
- Slave doesn't receive anything
BUT if I make the slave asks for new data continuously (polling, i.e. repeat step 1) I finally get the message.
I see in Wireshark that the message from the master is indeed received by the slave host. Just my app is not receiving it. What is more surprising, is that another master-slave pair running on the same network, with the same apps, is working fine, as well as my pair in the test environment.
The slave app uses UdpClient
in asynchronous mode. Here is how the listener is initialized:
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");
}
}
And here is the handler of a received packet:
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");
}
}
Of course, polling for new data is not an optimal solution and introduces unwanted delays. I'd like to know which phenomenon makes UdpClient lose incoming packets unless the same UdpClient has sent something before.