Reputation: 8192
In a project there is a device that listens on a specific UDP port and answers to the senders port.
For the sender and receiver I want the system to choose a free port, so I have the following code:
[Please excuse the vast masses of code, but this is the smallest example to show what behaviour occurs]
Sending code:
public class UdpSender
{
public int Port = 0; // some initially random port
public UdpClient UdpServer { get; set; }
public UdpSender()
{
UdpServer = CreateUdpClient();
// save the portnumber chosen by system to reuse it
Port = ((IPEndPoint)(UdpServer.Client.LocalEndPoint)).Port;
}
private UdpClient CreateUdpClient()
{
if (UdpServer != null)
{
UdpServer.Close();
}
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Port);
var udpServer = new UdpClient();
udpServer.ExclusiveAddressUse = false;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(localEndPoint);
return udpServer;
}
public void Send(byte[] arr)
{
UdpServer = CreateUdpClient();
int remotePortNumber = 6565;
var remoteEndPoint = new IPEndPoint(IPAddress.Broadcast, remotePortNumber);
try
{
UdpServer.Send(arr, arr.Length, remoteEndPoint);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
UdpServer.Close();
}
}
Receiving code:
public class UDPListener
{
private static int portNumber;
private UdpClient udpClient = null;
public List<DeviceData> DeviceList = new List<DeviceData>();
public UDPListener(int port)
{
portNumber = port;
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, portNumber);
udpClient = new UdpClient();
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(localEndPoint);
udpClient.Client.ReceiveBufferSize = 1 << 23;
}
public void StartListening()
{
this.udpClient.BeginReceive(Receive, new object());
}
private void Receive(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, portNumber);
byte[] bytes = udpClient.EndReceive(ar, ref ip);
string message = Encoding.ASCII.GetString(bytes);
DeviceList.Add(new DeviceData(message));
StartListening();
}
}
Bringing it together:
public class DeviceFinder
{
public IEnumerable<DeviceData> Find()
{
var sender = new UdpSender();
int port = sender.Port;
var listener = new UDPListener(port);
listener.StartListening();
sender.Send(new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 });
System.Threading.Thread.Sleep(5000); // wait some time for answers
return listener.DeviceList;
}
}
The Receive
method is never called with this approach. But in Wireshark, I can see an answer coming from the device.
What is wrong about this approach?
Before using this approach, I have used a fixed port and the call to CreateUdpClient
was added also. Seems to have something to with that, but I cannot figure it out.
Before I just created a UdpClient
with the fixed port just inside the receive / send method.
The previous version can be seen in this question. This works perfectly. But I fear if the fixed port is already in use, it does not work, hence this new approach.
Upvotes: 2
Views: 5328
Reputation: 311052
Just specify zero as your own port number. The system will allocate one when you bind or send. The source port number will accompany the datagram to the peer, who should reply to it.
Upvotes: 5