【问题标题】:can't receive UDP broadcast in windows 10 UWP from android app无法从 Android 应用程序接收 Windows 10 UWP 中的 UDP 广播
【发布时间】:2018-05-31 10:19:07
【问题描述】:
  • 我正在使用 Xamarin.forms 和 .net Standard 2 为共享代码编写 UWP 和 Android 应用程序。
  • 我正在尝试从两个应用程序发送和接收 UPD 广播,但问题是我只能从 android 应用程序按预期发送和接收,而 UWP 应用程序无法接收 UDP 广播数据包?
  • 我在windows上安装了wireshark,它可以接收来自两个应用程序的所有包。
  • 我为我的 app.uwp.exe 添加了防火墙规则(允许任何网络、任何端口、任何协议、任何 ip)我重新启动了电脑,但我的 UWP 应用仍然无法从 android 应用接收。

代码:

    using System.Threading.Tasks;
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    using System.Net.Sockets;
    using System.Net;    

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class ItemsPage : ContentPage
    {
     public async static Task<String> UDP_receive()
     {
        var myUDP = new UdpClient(8888);
        myUDP.EnableBroadcast = true;            
        var myResult = await myUDP.ReceiveAsync();
        myUDP.Close();
        return Encoding.ASCII.GetString(myResult.Buffer) + " : " + myResult.RemoteEndPoint.Address.ToString();
     }

     public async static Task UDP_Send()
     {
        var myUDP = new UdpClient();
        var RequestData = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
        myUDP.EnableBroadcast = true;
        await myUDP.SendAsync(RequestData, RequestData.Length, new IPEndPoint(IPAddress.Broadcast, 8888));
        myUDP.Close();
     }
    void Button1_click(object sender, EventArgs e)
     {
        StartListen();
        StartSending();   
     }
     async Task StartListen()
     {
        Exception eXX = null;
        while (eXX == null)
        {
            try
            {
                myText.Text += Environment.NewLine + await UDP_receive();
            }
            catch (Exception ex2)
            {
                eXX = ex2;
                log(ex2);
            }
        }
     }

     async Task StartSending()
     {
        Exception eXX = null;
        while (eXX == null)
        {
            try
            {
                await MyData.UDP_Send();
                await Task.Delay(1000);
            }
            catch (Exception ex2)
            {
                eXX = ex2;
                log(ex2);
            }
        }
     } 
   }    

Android 输出:
上午 11:57:11 : 192.168.1.155
上午 11:57:11:192.168.1.100
上午 11:57:12 : 192.168.1.155
上午 11:57:12:192.168.1.100
上午 11:57:13 : 192.168.1.155
上午 11:57:13:192.168.1.100
....
注意:192.168.1.100 是 Windows PC IP

UWP 输出:
上午 11:57:11 : 192.168.1.100
上午 11:57:12 : 192.168.1.100
上午 11:57:13 : 192.168.1.100
上午 11:57:14 : 192.168.1.100
上午 11:57:15 : 192.168.1.100
....

【问题讨论】:

  • 你有一个表单项目,不需要阻塞,因为它是表单构造函数中的一个内置块。所以删除等待(不需要)。同时删除 myUDP.Close();看起来当您收到第一个数据时,您正在关闭连接。
  • 感谢您的努力,我尝试了您的建议,但没有解决我的问题。我的 UWP 已经收到它发送的数据,但是它没有收到 android 发送的数据。
  • 可能有其他应用程序在使用该端口号,或者它可能被防火墙或病毒检查程序阻止。我会使用 cmd.exe >Netstat -a 并检查端口号是否已被使用。端口号是已注册的事件,除非在组(通常是多播组)中注册,否则端口号的事件列表中的第一个应用程序会获取消息。但是您没有使用多播 IP(224 到 239)。
  • UWP 在访问 8888 端口时接收到它的 UDP 广播数据包,但是 android 应用程序同时接收到它的数据包和 UWP 的数据包
  • @jdweng ,当我运行 Netstat -a 我得到:UDP 0.0.0.0:8888 仅当我的 UWP 运行时

标签: c# xamarin.forms uwp broadcast udpclient


【解决方案1】:

要接收 UDP 广播,请尝试将创建与绑定分开。例如,

            var myUDP = new UdpClient()
            {
                ExclusiveAddressUse = false,
                EnableBroadcast = true
            };

            IPEndPoint localIPEndPoint = new IPEndPoint(myIP.BroadcastIPAddress, 8888);
            myUDP.Client.Bind(localIPEndPoint);

根据我的经验,UdpClient(8888) 之类的短格式构造函数似乎过早地绑定了底层套接字。这可以防止更改 EnableBroadcast 属性。

此外,从平台到平台,我发现接收广播的唯一可靠方法是使用子网的实际广播地址。捕获这些信息很容易(?),如下所示。

    public class BroadcastAddress
    {
        public IPAddress IPAddress { get; set; }
        public IPAddress BroadcastIPAddress { get; set; }
        public NetworkInterfaceType NetworkInterfaceType { get; set; }
    }

    public static IEnumerable<BroadcastAddress> GetBroadcastAddresses()
    {
        List<BroadcastAddress> broadcastAddresses = new List<BroadcastAddress>();

        NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
        foreach (NetworkInterface networkInterface in networkInterfaces)
        {
            if (networkInterface != null 
                && (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211
                ||  networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet))
            {
                IPInterfaceProperties iPInterfaceProperties = networkInterface.GetIPProperties();
                UnicastIPAddressInformationCollection unicastIPAddressInformationCollection = iPInterfaceProperties.UnicastAddresses;
                foreach (UnicastIPAddressInformation unicastIPAddressInformation in unicastIPAddressInformationCollection)
                {
                    if (unicastIPAddressInformation.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        IPAddress broadcastIPAddress = 
                            new IPAddress(unicastIPAddressInformation.Address.Address | (UInt32.MaxValue ^ (UInt32)(unicastIPAddressInformation.IPv4Mask.Address)));

                        broadcastAddresses.Add(new BroadcastAddress()
                        {
                            IPAddress = unicastIPAddressInformation.Address,
                            BroadcastIPAddress = broadcastIPAddress,
                            NetworkInterfaceType = networkInterface.NetworkInterfaceType
                        });
                    }
                }
            }
        }

        return broadcastAddresses;
    }

当您处理移动设备时,您只需使用 Wireless80211 广播地址。在笔记本电脑或工作站上,它可能会变得稍微复杂一些。这些设备可以有多个网络接口和每个接口上的多个子网。因此,返回列表的原因。而且,这意味着您可能需要拥有多个 UdpClient 实例,每个子网一个。

这对于 OP 来说可能为时已晚。希望这些信息能帮助其他一些疲惫的搜索者试图让广播正常工作(他们可以停止用前额敲击桌子)。

【讨论】:

  • 尝试使用它在 UWP 上的 Xamarin.Forms 应用中接收 UDP 广播。如果我绑定到从您的代码返回的广播地址(看起来正确,地址:192.168.109.100,broadcastAddr:192.168.109.255),Bind 调用会引发套接字异常,“请求的地址在其上下文中无效”。如果我绑定到 IPAddress.Any,也不例外,但我没有收到任何数据。
  • @Nerdtron 请打开一个新问题,以便我们轻松共享代码片段。我脑子里唯一想到的就是调用的顺序。此外,如果您在评论中引用发布者姓名,他们会尽快收到通知。 ;-)
  • 我在这里创建了一个单独的问题:stackoverflow.com/questions/60420560/…。我能够让它工作并在那里发布详细信息。最终只使用了 IPAddress.Any。
  • 我引用了你的名字,但它似乎从我的评论中删除了该引用......它又做了一次。我认为,如果您引用您要回复的评论作者的姓名,则会将其删除,因为他们已经收到通知。
猜你喜欢
  • 2020-06-10
  • 2018-03-25
  • 1970-01-01
  • 2019-05-12
  • 2011-12-07
  • 1970-01-01
  • 2017-01-06
  • 2011-03-02
  • 1970-01-01
相关资源
最近更新 更多