我有两个应用程序(一个UWP和一个WPF)在同一台计算机上运行,应通过以下方式进行通信:WPF应用程序从USB端口读取数据,并将数据发送到UWP。UWP应用程序获取数据并消耗它。
现在,我一直在尝试使用UDP作为通信渠道实现这一目标,但是UWP应用程序没有收到任何东西。如果我创建两个UWP应用程序,则可以通过UDP通信而不会出现问题。不幸的是,我需要WPF一个!
我很确定这是一个非常普遍的情况,应该有一个简单的解决方案,但是我一直在搜索几天而没有达到解决方案。
顺便说一句,我找到了一个类似的问题,但是它是关于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发送者我尝试使用WinRT库,以便两个应用程序都可以在同一类中使用。为此,我
- 创建一个空的WPF项目
- 添加了C: Program Files(X86) Windows的引用套件 10 unionmetadata 10.0.17763.0 windows.winmd and c: program文件(x86)参考汇编 microsoft microsoft framework.netcore v4.5 v4.5 v4.5 system.runtime.windowsruntime.dlluntime.dll dll 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();
}
}
}
}
}
}
@xavierxie-msft不是重复的。我实际上自己找到了答案:
由于网络隔离,Windows取消了建立 两个UWP应用程序之间的插座连接(插座或Winsock) 在同一台机器上;是否通过本地回环地址 (127.0.0.0),或通过明确指定本地IP地址。为了 有关UWP应用程序可以与一个应用程序通信的机制的详细信息 另一个,请参阅应用程序到应用程序。
来源:https://learn.microsoft.com/en-us/windows/uwp/networking/sockets
因此,显然,这是一个"功能",而不是错误。恕我直言,微软再次以英尺射击。他们怎么会想到阻止Localhost请求!
无论如何,要解决问题,我找到了一个不同的解决方案:我正在使用应用程序服务(查看此内容https://learn.microsoft.com/en-us/windows/uwp/launch-resume/how-to-to-to-create-and-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)。
现在,我面临一个新问题:在成功将226条消息发送给UWP后,WPF的AppServiceConnection被关闭。但是,WPF继续从UWP接收消息。也许这篇文章可以帮助我解决这个新问题(我会及时通知您):UWP AppServiceConnection -sendResponsync返回appserviceresponsestatus.failure