UdpClient Receives Data on multiple listeners

随声附和 提交于 2019-12-11 05:26:27

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!