简体   繁体   English

如何使用 ZD7EFA19FBE7D32372FD5ADB607 中的 WPF 从 TCPClient 读取序列化和反序列化的 json object?

[英]How to read serialized and deserialized json object from TCPClient using WPF in C#?

I have a working code and its a window wpf application that start and stop the timer.我有一个工作代码及其启动和停止计时器的 window wpf 应用程序。 What i am struggling now to create TCPClient from my code, that will read a serialized and deserialized json object using TCP Socket.我现在正在努力从我的代码创建 TCPClient,它将使用 TCP 套接字读取序列化和反序列化的 json object。

// Requirement is when button is pressed from the start button on my window application. // 要求是从我的 window 应用程序上的开始按钮按下按钮时。

Pressing Start should start the echo process as described further below;按下 Start 应该开始回显过程,如下所述;

  • Repeat the below exactly every 500 ms每 500 毫秒重复一次以下操作
  • Create object that contains an initialized GUID创建包含已初始化 GUID 的 object
  • Serialize the object using a Json serializer使用 Json 序列化器序列化 object
  • Send the json string using a TCP socket to the echotool使用 TCP 套接字将 json 字符串发送到 echotool
    (The echotool will echo back all received data) (回显工具将回显所有接收到的数据)
  • Parse and assemble the echo'ed json data packet(s) and deserialize it back into an object解析并组装回显的 json 数据包并将其反序列化回 object
  • Add this echo result to the GUI Grid into the relevant columns将此回显结果添加到 GUI 网格的相关列中
    (Started = timestamp when this echo process started, Processed = timestamp after deserialization into an object, Elapsed = milliseconds elapsed from Started to Processed). (Started = 此 echo 进程开始时的时间戳,Processed = 反序列化为 object 后的时间戳,Elapsed = 从 Started 到 Processed 所用的毫秒数)。

// TCPClient i took from the microsoft documentation. // TCPClient 我取自微软文档。

    static void Connect(String server, String message)
    {
      try
      {
        // Create a TcpClient.
        // Note, for this client to work you need to have a TcpServer
        // connected to the same address as specified by the server, port
        // combination.
        Int32 port = 13000;
        TcpClient client = new TcpClient(server, port);
    
        // Translate the passed message into ASCII and store it as a Byte array.
        Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
    
        // Get a client stream for reading and writing.
       //  Stream stream = client.GetStream();
    
        NetworkStream stream = client.GetStream();
    
        // Send the message to the connected TcpServer.
        stream.Write(data, 0, data.Length);
    
        Console.WriteLine("Sent: {0}", message);
    
        // Receive the TcpServer.response.
    
        // Buffer to store the response bytes.
        data = new Byte[256];
    
        // String to store the response ASCII representation.
        String responseData = String.Empty;
    
        // Read the first batch of the TcpServer response bytes.
        Int32 bytes = stream.Read(data, 0, data.Length);
        responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
        Console.WriteLine("Received: {0}", responseData);
    
        // Close everything.
        stream.Close();
        client.Close();
      }
      catch (ArgumentNullException e)
      {
        Console.WriteLine("ArgumentNullException: {0}", e);
      }
      catch (SocketException e)
      {
        Console.WriteLine("SocketException: {0}", e);
      }
    
      Console.WriteLine("\n Press Enter to continue...");
      Console.Read();
    }

// Front end XAML //前端XAML

    <StackPanel Grid.Row="1" Orientation="Horizontal">
                <Button Padding="15 5" Margin="5" Content="Start"
                        Command="{x:Static local:WpfTimerWindow.StartCommand}"
                        CommandParameter="{x:Static local:WpfTimerWindow.Default}"/>

// Back end C# WPF // 后端 C# WPF

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Windows.Threading;
    using System.Diagnostics;
    using System.Timers;
    using System.ComponentModel;
    
    namespace PingApplication
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class WpfTimerWindow : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler? PropertyChanged;
    
            private readonly Timer timer = new Timer();
    
            private readonly Stopwatch stopwatch = new Stopwatch();
    
            public DateTime Now => DateTime.Now;
    
            public TimeSpan Elasped => stopwatch.Elapsed;
            public WpfTimerWindow()
            {
                //InitializeComponent();
                timer.Interval = 50;
                timer.Elapsed += OnTick;
                timer.Start();
                stopwatch.Start();
            }
    
            private void OnTick(object? sender, ElapsedEventArgs e)
            {
                if (PropertyChanged is PropertyChangedEventHandler propertyChanged)
                {
                    propertyChanged(this, NowArgs);
                    propertyChanged(this, ElaspedArgs);
                }
            }
    
            public static PropertyChangedEventArgs NowArgs { get; } = new PropertyChangedEventArgs(nameof(Now));
            public static PropertyChangedEventArgs ElaspedArgs { get; } = new PropertyChangedEventArgs(nameof(Elasped));
    
            public static RoutedUICommand StartCommand { get; } = new RoutedUICommand("Timer Start", "TimerStart", typeof(WpfTimerWindow));
            
            public static RoutedUICommand ResetCommand { get; } = new RoutedUICommand("Timer Stop", "TimerStop", typeof(WpfTimerWindow));
    
            public static ExecutedRoutedEventHandler ExecuteCommand { get; } = (_, e) =>
            {
                if (e.Parameter is WpfTimerWindow timer)
                {
                    if (e.Command == StartCommand)
                    {
                        timer.stopwatch.Start();
                    }
                    else if (e.Command == ResetCommand)
                    {
                        timer.stopwatch.Stop();
                    }
                   
                    
                    else return;
                    timer.OnTick(null, null);
                }
            };
            public static CanExecuteRoutedEventHandler CanExecuteCommand { get; } = (_, e) =>
            {
                if (e.Parameter is WpfTimerWindow timer)
                {
                    if (e.Command == StartCommand)
                    {
                        e.CanExecute = !timer.stopwatch.IsRunning;
                    }
                    else if (e.Command == ResetCommand)
                    {
                        e.CanExecute = timer.stopwatch.IsRunning;
                    }
                 
                }
            };
    
            public static WpfTimerWindow Default { get; } = new WpfTimerWindow();
        }
    }

Try to create separate model:尝试创建单独的 model:

public class MyModel
{
    public Guid Guid { get; set; }
    public DateTime Started { get; set; }
    public DateTime? Processed { get; set; }
    public DateTime? Elapsed { get; set; }
}

Usage (in your client code):用法(在您的客户端代码中):

...
var myModel = new MyModel
{
    Guid = Guid.NewGuid(),
    Started = DateTime.Now,
};
var message = Newtonsoft.Json.JsonConvert.SerializeObject(myModel);
var stream = client.GetStream();
var buffer = Encoding.Unicode.GetBytes(message);
stream.Write(buffer, 0, buffer.Length);
stream.Flush();
...

Usage (in your another client or server code):用法(在您的另一个客户端或服务器代码中):

...
var stream = client.GetStream();
var buffer = new byte[1024];
var response = new StringBuilder();
var bytes = stream.Read(buffer, 0, buffer.Length);

if (bytes != 0)
{
    response.Append(Encoding.Unicode.GetString(buffer, 0, bytes));

    while (stream.DataAvailable)
    {
        bytes = stream.Read(buffer, 0, buffer.Length);
        response.Append(Encoding.Unicode.GetString(buffer, 0, bytes));
    }

    var myModel = Newtonsoft.Json.JsonConvert.DeserializeObject<MyModel>(response);
    myModel.Processed = DateTime.Now;
    myModel.Elapsed = myModel.Processed - myModel.Started;

    // add the myModel to UI
    // In case of main thread issues, use App.Current.Dispatcher.Invoke(() => { addition here });
}
...

To develop more complex solution refer to this article about multi-threaded TCPSocket chat server.要开发更复杂的解决方案,请参阅这篇关于多线程 TCPSocket 聊天服务器的文章。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM