Reputation: 151
I am developing a UDP Client PC application. It is supposed to receive UDP datagrams from more than 4 devices.
The system behaves in the following way:
I am facing a strange issue when there are two or more devices in the network, such that:
endPoint
to the desired IPAddress and Port of the desired device using the discovered device list.myUDP.Receive(ref endPoint);
to receive UDP DatagramThis returns with the Datagram which was broadcasted by the second device in the network, rather than returning the response from the device with which I am trying to communicate. I have verified using the Wireshark that the response is sent from the device.
I tried looping through for a finite number of times to get the desired datagram.
// Some code which initializes the endPoint with desired IP Address and Port
...
// Some code which sends the data
...
// Some code which sets the IP Address of the device from which the response is expected
selectedIPAddress = IPAddress.Parse(labelIPAddressSettings.Text.Trim());
copyendPoint = endPoint;
// Listen to response
do
{
rexdDatagram = myUDP.Receive(ref endPoint);
if (endPoint.Address != selectedIPAddress)
{
// This datagram is not from the desired device
// Restore to the desired endpoint
endPoint = copyendPoint;
// Not sure if there is way to discard this enqueued datagram
}
i_timeout = i_timeout + 1;
if (i_timeout == 10)
{
// Datagram from the desired device has not been received
break;
}
// Not sure if the thread needs to sleep, debugging..
Thread.Sleep(1000);
} while (1);
Question: Is my code correct to loop within enqueued datagrams? Is there a way to discard previous datagrams and start afresh?
Upvotes: 0
Views: 133
Reputation: 7855
The parameter remoteEP
on the method UdpClient.Receive
is not meant for specifying from which remote endpoint to receive from, but rather to specify which remote endpoint sent the data. You cannot selectively receive only from a specific endpoint.
Instead, you'll have to receive everything from everyone, and discard the packages that were not sent from your desired remote endpoint. You can do this like so:
byte[] receivedData = null;
var attempts = 0;
while (attempts < 10)
{
var recvEp = new IPEndPoint(IPAddress.Any, 0);
readData = myUDP.Receive(ref recvEp);
if (recvEp.Address == selectedIPAddress)
{
// We received data from the correct remote source
receivedData = readData;
break;
}
attempts++;
}
This code will receive data from anywhere, and if it doesn't receive data from the correct endpoint within 10 attempts, it will stop. Resulting in receivedData
being null.
You might want to convert your code to wait for a certain amount of time not a certain amount of attempts, to increase the chances of actually receiving something. This could be done like so:
var start = DateTime.Now;
byte[] receivedData = null;
while((DateTime.Now - start).TotalSeconds < 10)
{
var recvEp = new IPEndPoint(IPAddress.Any, 0);
readData = myUDP.Receive(ref recvEp);
if (recvEp.Address == selectedIPAddress)
{
// We received data from the correct remote source
receivedData = readData;
break;
}
}
This code will try for 10 seconds, and stop after 10 seconds if nothing was received. This is not perfectly clean code, for example if you want to you can make this whole thing async.
Note: It is possible that both code snippets will result in an infinite loop, as myUDP.Receive(ref recvEp)
will block as long as there isn't any incoming data. So if all your remote endpoints decide to stop sending data at the same time, the receive call will never return
Upvotes: 1