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.