无法在 Xamarin.Forms 应用程序中接收 UDP 广播

unable to receive UDP broadcast in Xamarin.Forms app

我创建了一个测试 Xamarin.Forms 项目,选项卡式应用程序,支持 iOS、Android 和 UWP。具有样板起始代码的应用程序在所有 3 个平台上都能正确构建和 运行s。

正在尝试在应用程序中测试接收 UDP 广播。 UDP 广播是从同一子网上的另一台机器发送的(已经测试了来自另一台机器和同一台机器的广播,结果相同)。如果我在这台机器上 运行 一个独立的、非托管的 UDP 侦听器测试工具(我们内部编写的一个),我可以看到来自另一台机器的所有消息。

我将代码(如下所示)添加到 Xamarin.Forms 项目和 运行 本机上的 UWP 构建。 我看到的是,在调试输出中我收到了 "started receiving" 消息,然后没有其他消息。 我实际上没有收到消息(或者至少,回调未被调用)。我检查了 netstat,可以看到当我的 Xamarin.Forms 应用程序处于 运行ning 时,它绑定到指定的 UDP 端口。但是我的 OnUdpDataReceived 从未被调用过


编辑: 我在解决方案资源管理器中双击 UWP 项目的 Package.appxmanifest 文件,它显示了一个 UI 并且我检查了 "Capabilities >> Internet (Client & Server)" 认为这是一个权限问题,但这没有帮助。

编辑: 我通过创建两个控制台项目(一个发送方和一个接收方)验证了连通性。发件人只是永远循环,每秒发送一个测试 UDP 广播。接收器使用此处显示的相同代码。这些项目按预期工作。因此,相同的接收器代码在控制台项目中有效,但在 Xamarin.Forms 项目中无效。


首先是一个简单的UDP接收器class.

public class BaseUdpReceiver
{
    private UdpClient _udpClient;

    public BaseUdpReceiver()
    {
    }

    public void Start()
    {
        _udpClient = new UdpClient()
        {
            ExclusiveAddressUse = false,
            EnableBroadcast = true
        };
        _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, Constants.Network.SOME_CONSTANT_PORT_INTEGER));
        _udpClient.BeginReceive(OnUdpDataReceived, _udpClient);
        Debug.WriteLine($">>> started receiving");
    }

    private static void OnUdpDataReceived(IAsyncResult result)
    {
        Debug.WriteLine($">>> in receive");

        var udpClient = result.AsyncState as UdpClient;
        if (udpClient == null)
            return;

        IPEndPoint remoteAddr = null;
        var recvBuffer = udpClient.EndReceive(result, ref remoteAddr);

        Debug.WriteLine($"MESSAGE FROM: {remoteAddr.Address}:{remoteAddr.Port}, MESSAGE SIZE: {recvBuffer?.Length ?? 0}");

        udpClient.BeginReceive(OnUdpDataReceived, udpClient);
    }
}

然后,App.xaml.cs中的代码使用了这个class。

    public partial class App : Application
    {
        private BaseUdpReceiver _udpReceiver;

        public App()
        {
            InitializeComponent();

            DependencyService.Register<MockDataStore>();
            MainPage = new MainPage();

            _udpReceiver = new BaseUdpReceiver();
            _udpReceiver.Start();
        }

        protected override void OnStart()
        {
        }

        protected override void OnSleep()
        {
        }

        protected override void OnResume()
        {
        }
    }


版本信息

Visual Studio 2019 Enterprise v16.4.5
Xamarin 16.4.000.322 (d16-4@ddfd842)
Windows 10 64-bit v1909 (OS Build 18363.657)

Microsoft.NETCore.UniversalWindowsPlatform, v6.2.9
NETStandard.Library, v2.0.3
Xamarin.Essentials, v1.5.0
Xamarin.Forms, v4.5.0.356

在 MS 支持的帮助下,它适用于 UWP 和 Android。

请注意,考虑到以下因素,原始 post 中提供的代码是正确且有效的。

  • UWP
    • 由于 UWP 的网络隔离,你不能在同一台机器上广播和接收,虽然这在控制台应用程序中工作正常,但它不适用于 Xamarin.Forms UWP,所以技巧是你只需要从不同的机器广播
    • 需要调整Package.appxmanifest>>能力设置
      • 在 2 台机器上(wifi 笔记本电脑和有线台式机),我发现检查 "Internet (Client)" 和 "Internet (Client & Server)" 就足够了
      • 在具有 2 个网卡的第 3 台台式机上,一个插入一个拔出,它仍然无法使用上述选项,还需要检查 "Private Networks (Client & Server)"
  • Android
    • 模拟器似乎创建了自己的子网,您可以通过检查模拟器的网络设置看到这一点,它显然与 运行[=34= 所在的桌面计算机不在同一个子网中]
    • 因此,您无法在 Android 模拟器中以简单的方式获得 UDP 广播(除了我没有试验过的某种转发方案)
    • 已验证使用物理 Android 平板电脑(使用 Samsung Galaxy Tab A 8" 测试),它可以工作并且我能够接收 UDP 广播
    • 请注意,在 Android 上,我不必像使用 UWP 那样更改默认设置的任何权限,它可以正常工作
  • iOS
    • 到目前为止,还没有在物理 iOS 设备上测试过,我有一个 iPhone,但我使用的是云 Mac 构建服务器,所以无法测试在我的设备上
    • 到了处理 iOS 的时候,看来我可能需要找一个本地 Mac