У меня есть два приложения (одно UWP и одно WPF), работающие на одной машине, которые должны взаимодействовать следующим образом:
Приложение WPF считывает данные с USB-порта и отправляет данные в UWP.
приложение UWP получает данные и потребляет их.
Теперь я пытался добиться этого, используя UDP в качестве канала связи, но приложение UWP ничего не получает.
Если я создаю два приложения UWP, они могут без проблем общаться через UDP. К сожалению, мне нужен WPF!
Я почти уверен, что это очень распространенный сценарий, и должно быть простое решение, но я искал несколько дней, не найдя решения.
Кстати, я нашел похожий вопрос , но речь идет о C ++, пока мне нужно решение C #.
Edit:
Вот минимальный пример, может быть, это поможет пролить свет на проблему.
UWP Listener
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 и C: \ Program Files (x86) \ Справочные сборки \ 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();
}
}
}
}
}
}