Home > Software design >  How to read serialized and deserialized json object from TCPClient using WPF in C#?
How to read serialized and deserialized json object from TCPClient using WPF in C#?

Time:09-13

I have a working code and its a window wpf application that start and stop the timer. What i am struggling now to create TCPClient from my code, that will read a serialized and deserialized json object using TCP Socket.

// Requirement is when button is pressed from the start button on my window application.

Pressing Start should start the echo process as described further below;

  • Repeat the below exactly every 500 ms
  • Create object that contains an initialized GUID
  • Serialize the object using a Json serializer
  • Send the json string using a TCP socket to the 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
  • Add this echo result to the GUI Grid into the relevant columns
    (Started = timestamp when this echo process started , Processed = timestamp after deserialization into an object , Elapsed = milliseconds elapsed from Started to Processed).

// TCPClient i took from the microsoft documentation.

    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

    <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

    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();
        }
    }

CodePudding user response:

Try to create separate 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.

  • Related