【问题标题】:unable to receive UDP broadcast in Xamarin.Forms app无法在 Xamarin.Forms 应用中接收 UDP 广播
【发布时间】:2020-06-10 17:14:24
【问题描述】:

我创建了一个测试 Xamarin.Forms 项目,即选项卡式应用,支持 iOS、Android 和 UWP。带有样板启动代码的应用程序可以在所有 3 个平台上正确构建和运行。

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

我将代码(如下所示)添加到 Xamarin.Forms 项目并在这台机器上运行 UWP 构建。 我看到的是在调试输出中我收到“开始接收”消息,然后什么都没有。我实际上并没有收到消息(或者至少,回调没有被调用)。我检查了 netstat,可以看到当我的 Xamarin.Forms 应用程序运行时,它绑定到指定的 UDP 端口。但是我的 OnUdpDataReceived 永远不会被调用


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

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


首先是一个简单的 UDP 接收器类。

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 中使用这个类的代码。

    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

【问题讨论】:

  • 您好,您可以检查一下是否可以连接到主机。通过使用示例代码检查连接:docs.microsoft.com/en-us/dotnet/api/…
  • @JuniorJiang-MSFT 谢谢!是的,我能够验证是否存在连接。我创建了几个控制台项目、一个发送者和一个接收者,并验证了它们的通信是否正确。接收器使用的是我在此处显示的相同代码。接收器在控制台应用程序中工作,但在 Xamarin.Forms 应用程序中不工作。
  • 我觉得你可以试试async/awaitmethond 来调用methond,网络任务更好的在线程中运行。这与控制台应用程序处理网络任务不同。看看这个关于 async/await 的文档。这里有一个UWP sample code,关于使用 UDP 供参考。
  • @JuniorJiang-MSFT 无法等待 UdpClient.BeginReceive,尝试等待会出现错误,表明其不可等待。您链接到的示例不使用 UdpClient,但是我编写的代码基于 MS 文档提供的有关使用 UdpClient 的内容。

标签: xamarin.forms network-programming udp


【解决方案1】:

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

请注意,鉴于以下注意事项,原始帖子中提供的代码是正确且有效的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 2018-08-19
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多