UWP和WPF之间的(UDP)通信

问题描述 投票:0回答:1

我有两个应用程序(一个UWP和一个WPF)在同一台机器上运行,应按如下方式进行通信:WPF应用程序从USB端口读取数据并将数据发送到UWP。 UWP应用程序获取数据并使用它。

现在,我一直在尝试使用UDP作为通信渠道来实现这一点,但UWP应用程序没有收到任何东西。如果我创建两个UWP应用程序,他们可以通过UDP进行通信而不会出现问题。不幸的是,我需要一个WPF!

我很确定这是一个非常常见的场景,应该有一个简单的解决方案,但我一直在寻找没有达成解决方案的日子。

顺便说一句,我发现了一个similar question,但它是关于C ++而我需要一个C#解决方案。

编辑:

这是一些最小的运行示例,也许这有助于揭示问题。

UWP听众

using System;
using System.Diagnostics;
using System.IO;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UDP1_UWP
{
    public sealed partial class DatagramSocketPage : Page
    {
        public DatagramSocketPage()
        {
            this.InitializeComponent();
        }

        static string ClientPortNumber = "1336";
        static string ServerPortNumber = "1337";

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            this.StartServer();
        }

        private async void StartServer()
        {
            try
            {
                var serverDatagramSocket = new Windows.Networking.Sockets.DatagramSocket();


                serverDatagramSocket.MessageReceived += ServerDatagramSocket_MessageReceived;

                this.serverListBox.Items.Add("server is about to bind...");


                await serverDatagramSocket.BindServiceNameAsync(DatagramSocketPage.ServerPortNumber);

                this.serverListBox.Items.Add(string.Format("server is bound to port number {0}", DatagramSocketPage.ServerPortNumber));
            }
            catch (Exception ex)
            {
                Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
                this.serverListBox.Items.Add(webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
            }
        }

        private async void ServerDatagramSocket_MessageReceived(Windows.Networking.Sockets.DatagramSocket sender, Windows.Networking.Sockets.DatagramSocketMessageReceivedEventArgs args)
        {
            string request;
            using (DataReader dataReader = args.GetDataReader())
            {
                request = dataReader.ReadString(dataReader.UnconsumedBufferLength).Trim();
            }

            await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server received the request: \"{0}\"", request)));

            // Echo the request back as the response.
            using (Stream outputStream = (await sender.GetOutputStreamAsync(args.RemoteAddress, DatagramSocketPage.ClientPortNumber)).AsStreamForWrite())
            {
                using (var streamWriter = new StreamWriter(outputStream))
                {
                    await streamWriter.WriteLineAsync(request);
                    await streamWriter.FlushAsync();
                }
            }

            await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server sent back the response: \"{0}\"", request)));


        }

    }
}

WPF Sender我尝试使用WinRT libriaries,因此两个应用程序都使用相同的类。要做到这一点我

  1. 创建了一个空的WPF项目
  2. 添加了对C:\ Program Files(x86)\ Windows Kits \ 10 \ UnionMetadata \ 10.0.17763.0 \ Windows.winmd和C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ Framework.NETCore \ v4.5 \ System的引用.Runtime.WindowsRuntime.dll

现在我可以在WPF应用程序中使用以下命名空间:

  • 使用Windows.Networking;
  • 使用Windows.Networking.Sockets;
  • 使用Windows.Storage.Streams;

这是代码:

Program.cs中

using System;
using XSensUDPSender.UDP;

namespace XSensUDPServer
{
    class Program
    {

        static void Main(string[] args)
        {
            UDPClient c = new UDPClient();
            c.StartClientAsync();

            string text;
            do
            {
                Console.WriteLine("Message to send: ");
                text = Console.ReadLine();
                c.SendMessageAsync(text);
            } while (text != "quit");

        }
    }
}

UDPClient.cs

using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace XSensUDPSender.UDP
{
    class UDPClient
    {
        private DatagramSocket clientDatagramSocket;
        private HostName hostName;
        private string ClientPortNumber = "1336";
        private string ServerPortNumber = "1337";

        public UDPClient(string aClientPort = "1336", string aServerPort = "1337")
        {
            ClientPortNumber = aClientPort;
            ServerPortNumber = aServerPort;
        }

        public async void StartClientAsync()
        {
            try
            {
                // Create the DatagramSocket and establish a connection to the echo server.
                clientDatagramSocket = new Windows.Networking.Sockets.DatagramSocket();

                clientDatagramSocket.MessageReceived += ClientDatagramSocket_MessageReceived;

                // The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
                hostName = new Windows.Networking.HostName("localhost");

                Console.WriteLine("CLIENT is about to bind...");
                await clientDatagramSocket.BindServiceNameAsync(ClientPortNumber);
                Console.WriteLine(string.Format("CLIENT is bound to port number {0}", ClientPortNumber));


            }
            catch (Exception ex)
            {
                Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
                Debug.WriteLine(webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
            }
        }

        private void ClientDatagramSocket_MessageReceived(Windows.Networking.Sockets.DatagramSocket sender, Windows.Networking.Sockets.DatagramSocketMessageReceivedEventArgs args)
        {
            string response;
            using (DataReader dataReader = args.GetDataReader())
            {
                response = dataReader.ReadString(dataReader.UnconsumedBufferLength).Trim();
                Console.WriteLine("CLIENT RECEIVED: " + response);
            }

        }


        public async Task SendMessageAsync(string request)
        {
            // Send a request to the echo server.
            using (var serverDatagramSocket = new Windows.Networking.Sockets.DatagramSocket())
            {
                using (Stream outputStream = (await serverDatagramSocket.GetOutputStreamAsync(hostName, ServerPortNumber)).AsStreamForWrite())
                {
                    using (var streamWriter = new StreamWriter(outputStream))
                    {
                        await streamWriter.WriteLineAsync(request);
                        await streamWriter.FlushAsync();
                    }
                }
            }


        }

    }
}
c# wpf uwp udp communication
1个回答
0
投票

@ XavierXie-MSFT不重复。我实际上自己找到了答案:

由于网络隔离,Windows不允许在同一台机器上运行的两个UWP应用程序之间建立套接字连接(套接字或WinSock);是通过本地环回地址(127.0.0.0),还是通过显式指定本地IP地址。有关UWP应用程序可以相互通信的机制的详细信息,请参阅App-to-app通信。

资料来源:https://docs.microsoft.com/en-us/windows/uwp/networking/sockets

所以,显然,这是一个“功能”,而不是一个错误。虽然,恕我直言,微软再次开枪。他们怎么能想到阻止localhost请求!??

无论如何,为了解决这个问题,我找到了一个不同的解决方案:我正在使用App Services(请查看https://docs.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-and-consume-an-app-service)。所以,现在我有我的UWP应用程序,其中包括后台应用程序服务。

整体基础设施可以设想如下:UWP < - >后台应用服务< - > WPF

我受到了这样的启发:https://csharp.christiannagel.com/2018/10/09/desktopbridge/

UWP应用程序将AppServiceConnection实例化为后台服务。 WPF应用程序还将AppServiceConnection实例化为后台服务。后台服务有两个AppServiceConnection:一个绑定到UWP应用程序,另一个绑定到WPF应用程序。

当UWP(相应的WPF)想要与WPF(相应的UWP)通信时,它会向后台服务发送一条消息。后台服务将消息转发给WPF(相应的UWP),获得响应并将响应转发回UWP(相应的WPF)。

现在我面临一个新问题:WPF的AppServiceConnection在成功向UWP发送226条消息后关闭。然而,WPF不断收到来自UWP的消息。也许这篇文章可以帮助我解决这个新问题(我会告诉你):UWP AppServiceConnection - SendResponseAsync returns AppServiceResponseStatus.Failure

© www.soinside.com 2019 - 2024. All rights reserved.