问题
I have an application which implements an autodiscovery mechanism and I'm having an issue with the UdpClient. It works fine as long as a single instance of the application is open. However, when a second instance is open only the first receives the unicast packets. Interestingly enough, a similar application that implements the same mechanism doesn't seem to have this issue. Any suggestions?
class AutoDiscovery
{
private UdpClient Udp;
private IPEndPoint BroadcastEP = new IPEndPoint(IPAddress.Broadcast, 1234);
private List<byte> AutoDiscoverPacket = new List<byte>();
public ObservableCollection<DiscoveredDevice> DiscoveredDevices = new ObservableCollection<DiscoveredDevice>();
public AutoDiscovery()
{
Udp = new UdpClient();
Udp.ExclusiveAddressUse = false;
Udp.EnableBroadcast = true;
Udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
Udp.Client.Bind(new IPEndPoint(IPAddress.Any, 1234));
AutoDiscoverPacket.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
AutoDiscoverPacket.AddRange(Encoding.ASCII.GetBytes("SomeStaticString"));
while (AutoDiscoverPacket.Count < 123)
{
AutoDiscoverPacket.Add(0x00);
}
ReceiveDataAsync(ReceiveDataCallback);
}
~AutoDiscovery()
{
if (Udp != null)
{
try
{
Udp.Close();
}
finally
{
}
}
}
public void Discover()
{
DiscoveredDevices.Clear();
Udp.Send(AutoDiscoverPacket.ToArray(), AutoDiscoverPacket.Count, BroadcastEP);
}
private void ReceiveDataAsync(Action<UdpReceiveResult> Callback)
{
Task.Run(async () =>
{
try
{
while (true)
{
//IPEndPoint object will allow us to read datagrams sent from any source.
UdpReceiveResult receivedResults = await Udp.ReceiveAsync();
Callback(receivedResults);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
});
}
private void ReceiveDataCallback(UdpReceiveResult Result)
{
// Do stuff here
}
}
}
回答1:
It is not useful to bind more than one socket to the same combination of IP address and port, and by default it's not even possible. Only if you set the SO_REUSEADDR
option (SocketOptionName.ReuseAddress
in managed code) can sockets share the port on the same IP address, and even then the behavior is non-deterministic (generally, one or the other socket will receive datagrams, but not both).
If you can configure your sockets to use different IP addresses (e.g. you have multiple network adapters on the same computer), then they can listen on the same port.
A more general approach though would be to use UDP Multicast. Then each server can join the multicast group to receive discovery datagrams, responding with a unique port # that they've configured for main communication.
Here are some related Q&A:
C# UDP server multiple instances ipv6 same port
Listening to broadcasts when server and client are on the same machine
The second one actually involves a bug in the UWP implementation of UDP sockets, but the question includes some good detail on the basic idea of using multicast to accomplish this goal.
来源:https://stackoverflow.com/questions/47083069/udpclient-receives-data-on-multiple-listeners