Updated
This commit is contained in:
@@ -11,10 +11,4 @@
|
||||
<ProjectReference Include="..\EonaCat.Connections\EonaCat.Connections.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="client.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,82 +1,310 @@
|
||||
using EonaCat.Connections.Models;
|
||||
using EonaCat.Connections.Processors;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace EonaCat.Connections.Client.Example
|
||||
{
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/license for full license details.
|
||||
|
||||
public class Program
|
||||
{
|
||||
private static NetworkClient _client;
|
||||
private const bool UseProcessor = true;
|
||||
private const bool IsHeartBeatEnabled = false;
|
||||
private static List<NetworkClient> _clients = new List<NetworkClient>();
|
||||
private static long clientCount = 1;
|
||||
private static long clientsConnected = 0;
|
||||
private static string _jsonContent;
|
||||
|
||||
//public static string SERVER_IP = "10.40.11.22";
|
||||
public static string SERVER_IP = "127.0.0.1";
|
||||
|
||||
private static Dictionary<NetworkClient, JsonDataProcessor<dynamic>> _clientsProcessors = new Dictionary<NetworkClient, JsonDataProcessor<dynamic>>();
|
||||
private static bool testDataProcessor;
|
||||
|
||||
public static bool WaitForMessage { get; private set; }
|
||||
public static bool PressEnterForNextMessage { get; private set; }
|
||||
public static bool ToConsoleOnly { get; private set; } = true;
|
||||
public static bool UseJson { get; private set; } = true;
|
||||
public static bool TESTBYTES { get; private set; }
|
||||
public static bool UseJsonProcessorTest { get; private set; } = false;
|
||||
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
await CreateClientAsync().ConfigureAwait(false);
|
||||
for (long i = 0; i < clientCount; i++)
|
||||
{
|
||||
var clientName = $"User {i}";
|
||||
var client = await CreateClientAsync().ConfigureAwait(false);
|
||||
_clients.Add(client);
|
||||
|
||||
if (testDataProcessor)
|
||||
{
|
||||
_clientsProcessors[client] = new JsonDataProcessor<dynamic>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = StartClientAsync(clientName, client);
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!_client.IsConnected)
|
||||
{
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
continue;
|
||||
}
|
||||
string message = string.Empty;
|
||||
|
||||
Console.Write("Enter message to send (or 'exit' to quit): ");
|
||||
var message = Console.ReadLine();
|
||||
if (WaitForMessage)
|
||||
{
|
||||
Console.Write("Enter message to send (or 'exit' to quit): ");
|
||||
message = Console.ReadLine();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(message) && message.Equals("exit", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await _client.DisconnectAsync().ConfigureAwait(false);
|
||||
foreach (var client in _clients)
|
||||
{
|
||||
await client.DisconnectClientAsync().ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var jsonUrl = "https://samples.json-format.com/employees/json/employees_500KB.json";
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(_jsonContent) && UseJson)
|
||||
{
|
||||
using var httpClient = new HttpClient();
|
||||
_jsonContent = await httpClient.GetStringAsync(jsonUrl);
|
||||
|
||||
var jsonSize = Encoding.UTF8.GetByteCount(_jsonContent);
|
||||
WriteToLog($"Using large JSON file (size: {jsonSize / 1024 / 1024} MB)");
|
||||
}
|
||||
|
||||
if (UseJson)
|
||||
{
|
||||
message = _jsonContent;
|
||||
}
|
||||
|
||||
if (UseJsonProcessorTest)
|
||||
{
|
||||
foreach (var client in _clients)
|
||||
{
|
||||
var processor = _clientsProcessors[client];
|
||||
processor.OnProcessTextMessage += (sender, e) =>
|
||||
{
|
||||
WriteToLog($"Processed message from {e.ClientName}: {e.Text}");
|
||||
};
|
||||
processor.OnProcessMessage += (sender, e) =>
|
||||
{
|
||||
WriteToLog($"Processed JSON message from {e.ClientName} ({e.ClientEndpoint}): {e.RawData}");
|
||||
};
|
||||
processor.MaxAllowedBufferSize = 10 * 1024 * 1024; // 10 MB
|
||||
processor.MaxMessagesPerBatch = 5;
|
||||
var json = _jsonContent;
|
||||
|
||||
while (true)
|
||||
{
|
||||
processor.Process(json, "TestClient");
|
||||
await Task.Delay(100).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
WriteToLog($"Failed to download large JSON file: {exception.Message}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
await _client.SendAsync(message).ConfigureAwait(false);
|
||||
foreach (var client in _clients)
|
||||
{
|
||||
if (TESTBYTES)
|
||||
{
|
||||
var bytes = new byte[] { 0x00, 0x04, 0x31, 0x32, 0x30, 0x30 };
|
||||
await client.SendAsync(bytes).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await client.SendAsync(message).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task CreateClientAsync()
|
||||
private static async Task StartClientAsync(string clientName, NetworkClient client)
|
||||
{
|
||||
await client.ConnectAsync().ConfigureAwait(false);
|
||||
|
||||
// Send nickname
|
||||
await client.SendNicknameAsync(clientName);
|
||||
|
||||
// Send a message
|
||||
await client.SendAsync($"Hello server, my name is {clientName}!");
|
||||
}
|
||||
|
||||
private static async Task<NetworkClient> CreateClientAsync()
|
||||
{
|
||||
var config = new Configuration
|
||||
{
|
||||
Protocol = ProtocolType.TCP,
|
||||
Host = "127.0.0.1",
|
||||
Host = SERVER_IP,
|
||||
Port = 1111,
|
||||
UseSsl = true,
|
||||
UseAesEncryption = true,
|
||||
UseSsl = false,
|
||||
UseAesEncryption = false,
|
||||
EnableHeartbeat = IsHeartBeatEnabled,
|
||||
AesPassword = "EonaCat.Connections.Password",
|
||||
Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2("client.pfx", "p@ss"),
|
||||
};
|
||||
|
||||
_client = new NetworkClient(config);
|
||||
|
||||
_client.OnGeneralError += (sender, e) =>
|
||||
Console.WriteLine($"Error: {e.Message}");
|
||||
var client = new NetworkClient(config);
|
||||
|
||||
// Subscribe to events
|
||||
_client.OnConnected += async (sender, e) =>
|
||||
client.OnConnected += (sender, e) =>
|
||||
{
|
||||
WriteToLog($"Connected to server at {e.RemoteEndPoint}");
|
||||
Console.WriteLine($"Connected to server at {e.RemoteEndPoint}");
|
||||
|
||||
// Set nickname
|
||||
await _client.SendNicknameAsync("TestUser");
|
||||
|
||||
// Send a message
|
||||
await _client.SendAsync("Hello server!");
|
||||
Console.Title = $"Total clients {++clientsConnected}";
|
||||
};
|
||||
|
||||
_client.OnDataReceived += (sender, e) =>
|
||||
Console.WriteLine($"Server says: {(e.IsBinary ? $"{e.Data.Length} bytes" : e.StringData)}");
|
||||
|
||||
_client.OnDisconnected += (sender, e) =>
|
||||
if (UseProcessor)
|
||||
{
|
||||
Console.WriteLine("Disconnected from server");
|
||||
_clientsProcessors[client] = new JsonDataProcessor<object>();
|
||||
_clientsProcessors[client].OnError += (sender, e) =>
|
||||
{
|
||||
Console.WriteLine($"Processor error: {e.Message}");
|
||||
};
|
||||
|
||||
_clientsProcessors[client].OnMessageError += (sender, e) =>
|
||||
{
|
||||
Console.WriteLine($"Processor message error: {e.Message}");
|
||||
};
|
||||
|
||||
_clientsProcessors[client].OnProcessTextMessage += (sender, e) =>
|
||||
{
|
||||
Console.WriteLine($"Processed text message from {e.ClientName}: {e.Text}");
|
||||
};
|
||||
|
||||
_clientsProcessors[client].OnProcessMessage += (sender, e) =>
|
||||
{
|
||||
ProcessMessage(e.RawData, e.ClientName, e.ClientEndpoint ?? "Unknown endpoint");
|
||||
};
|
||||
}
|
||||
|
||||
client.OnDataReceived += (sender, e) =>
|
||||
{
|
||||
if (UseProcessor)
|
||||
{
|
||||
_clientsProcessors[client].Process(e, currentClientName: e.Nickname);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteToLog($"Server says: {(e.IsBinary ? $"{e.Data.Length} bytes" : "We got a json message")}");
|
||||
Console.WriteLine($"{e.StringData}");
|
||||
|
||||
if (PressEnterForNextMessage)
|
||||
{
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Console.WriteLine("Connecting to server...");
|
||||
await _client.ConnectAsync();
|
||||
client.OnDisconnected += (sender, e) =>
|
||||
{
|
||||
var message = string.Empty;
|
||||
if (e.Reason == DisconnectReason.LocalClosed)
|
||||
{
|
||||
if (e.Exception != null)
|
||||
{
|
||||
message = $"Disconnected from server (local close). Exception: {e.Exception.Message}";
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "Disconnected from server (local close).";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e.Exception != null)
|
||||
{
|
||||
message = $"Disconnected from server (remote close). Reason: {e.Reason}. Exception: {e.Exception.Message}";
|
||||
}
|
||||
else
|
||||
{
|
||||
message = $"Disconnected from server (remote close). Reason: {e.Reason}";
|
||||
}
|
||||
}
|
||||
|
||||
WriteToLog(message);
|
||||
Console.WriteLine(message);
|
||||
Console.Title = $"Total clients {--clientsConnected}";
|
||||
};
|
||||
|
||||
client.OnEncryptionError += Client_OnEncryptionError;
|
||||
client.OnGeneralError += Client_OnGeneralError;
|
||||
client.OnSslError += Client_OnSslError;
|
||||
return client;
|
||||
}
|
||||
|
||||
private static void ProcessMessage(object message, string clientName, string remoteEndpoint)
|
||||
{
|
||||
WriteToLog($"Processed message from {clientName} ({remoteEndpoint}): {message}");
|
||||
if (PressEnterForNextMessage)
|
||||
{
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Client_OnSslError(object? sender, EventArguments.ErrorEventArgs e)
|
||||
{
|
||||
WriteToLog($"SSL error: {e.Message} => {e.Exception?.Message} => {e.Nickname}");
|
||||
}
|
||||
|
||||
private static void Client_OnGeneralError(object? sender, EventArguments.ErrorEventArgs e)
|
||||
{
|
||||
WriteToLog($"General error: {e.Message} => {e.Exception?.Message} => {e.Nickname}");
|
||||
}
|
||||
|
||||
private static void Client_OnEncryptionError(object? sender, EventArguments.ErrorEventArgs e)
|
||||
{
|
||||
WriteToLog($"Encryption error: {e.Message} => {e.Exception?.Message} => {e.Nickname}");
|
||||
}
|
||||
|
||||
public static void WriteToLog(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ToConsoleOnly)
|
||||
{
|
||||
var dateTimeNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
Console.WriteLine($"{dateTimeNow}: {message}");
|
||||
return;
|
||||
}
|
||||
|
||||
var logFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "client_log.txt");
|
||||
var logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}{Environment.NewLine}";
|
||||
|
||||
if (!File.Exists(logFilePath))
|
||||
{
|
||||
File.WriteAllText(logFilePath, logMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (new FileInfo(logFilePath).Length > 5 * 1024 * 1024) // 5 MB
|
||||
{
|
||||
var archiveFilePath = Path.Combine(Path.GetDirectoryName(logFilePath) ?? ".", $"client_log_{DateTime.Now:yyyyMMdd_HHmmss}.txt");
|
||||
File.Move(logFilePath, archiveFilePath);
|
||||
File.WriteAllText(logFilePath, logMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
File.AppendAllText(logFilePath, logMessage);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore logging errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user