Init
This commit is contained in:
88
Server/DataGenerator.cs
Normal file
88
Server/DataGenerator.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Domain;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public class DataGenerator
|
||||
{
|
||||
private static readonly Random _random = new Random();
|
||||
|
||||
private readonly int _minNewPackages;
|
||||
private readonly int _maxPreviousPackages;
|
||||
private readonly TimeSpan _generationInterval;
|
||||
private readonly LinkedList<Data> _cache = new LinkedList<Data>();
|
||||
private readonly ConcurrentDictionary<long, Data> _dict = [];
|
||||
private readonly object _lock = new object();
|
||||
private long _maxRequestedIndex = 0;
|
||||
private Task _generationTask;
|
||||
private CancellationTokenSource _cts = new();
|
||||
|
||||
public DataGenerator(int minNewPackages = 50, int maxPreviousPackages = 50, TimeSpan? generationInterval = null)
|
||||
{
|
||||
_minNewPackages = Math.Max(minNewPackages, 5);
|
||||
_maxPreviousPackages = Math.Max(maxPreviousPackages, 5);
|
||||
_generationInterval = generationInterval ?? TimeSpan.FromSeconds(1);
|
||||
_generationTask = Task.Run(() => GenerateInBackground(_cts.Token));
|
||||
}
|
||||
|
||||
private void GenerateInBackground(CancellationToken token)
|
||||
{
|
||||
var firstData = GenerateRandomData(0);
|
||||
_cache.AddLast(firstData);
|
||||
_dict[firstData.PackageIndex] = firstData;
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
//await Task.Delay(_generationInterval, token);
|
||||
var first = _cache.First!.Value;
|
||||
var last = _cache.Last!.Value;
|
||||
if (last.PackageIndex - _maxRequestedIndex < _minNewPackages)
|
||||
{
|
||||
var data = GenerateRandomData(last.PackageIndex + 1);
|
||||
_cache.AddLast(data);
|
||||
_dict[data.PackageIndex] = data;
|
||||
}
|
||||
if (_maxRequestedIndex - first.PackageIndex > _maxPreviousPackages)
|
||||
{
|
||||
_cache.RemoveFirst();
|
||||
_dict.TryRemove(first.PackageIndex, out _);
|
||||
}
|
||||
//System.Console.WriteLine($"[{first.PackageIndex}; {last.PackageIndex}]");
|
||||
}
|
||||
}
|
||||
|
||||
public Data? GetPackage(long packageIndex)
|
||||
{
|
||||
var res = _dict.TryGetValue(packageIndex, out var value);
|
||||
_maxRequestedIndex = Math.Max(_maxRequestedIndex, packageIndex);
|
||||
return res ? value : null;
|
||||
}
|
||||
|
||||
private Data GenerateRandomData(long packageNumber)
|
||||
{
|
||||
var alpha = _random.NextDouble();
|
||||
var beta = _random.NextDouble() * (1 - alpha);
|
||||
var theta = 1 - alpha - beta;
|
||||
var signalQuality = _random.NextDouble();
|
||||
|
||||
return new Data(
|
||||
ConcentrationIndex: _random.NextDouble(),
|
||||
RelaxationIndex: _random.NextDouble(),
|
||||
CognitiveControl: _random.NextDouble(),
|
||||
CognitiveLoad: _random.NextDouble(),
|
||||
Alpha: alpha,
|
||||
Beta: beta,
|
||||
Theta: theta,
|
||||
Smr: _random.NextDouble(),
|
||||
MuWave: _random.NextDouble(),
|
||||
Artifact: signalQuality < 0.5,
|
||||
SignalQuality: signalQuality,
|
||||
PackageIndex: packageNumber,
|
||||
TimeOfDataGenerate: DateTime.Now
|
||||
);
|
||||
}
|
||||
}
|
||||
105
Server/HttpServer.cs
Normal file
105
Server/HttpServer.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Domain;
|
||||
using Domain.Dto;
|
||||
|
||||
namespace NetworkTest;
|
||||
|
||||
public class HttpServer : IServer
|
||||
{
|
||||
private readonly HttpListener _listener;
|
||||
private readonly string _url;
|
||||
private CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private Func<long, Data?> _getData;
|
||||
private Action<Data, HttpListenerResponse> _writeResponse;
|
||||
|
||||
public HttpServer(Func<long, Data?> getData, Action<Data, HttpListenerResponse> writeResponse, string url = "http://*:5555/")
|
||||
{
|
||||
_getData = getData;
|
||||
_writeResponse = writeResponse;
|
||||
_url = url;
|
||||
_listener = new HttpListener();
|
||||
_listener.Prefixes.Add(_url);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_cts = new CancellationTokenSource();
|
||||
_listener.Start();
|
||||
Task.Run(() => ListenAsync(_cts.Token));
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_listener.Stop();
|
||||
}
|
||||
|
||||
private async Task ListenAsync(CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var context = await _listener.GetContextAsync();
|
||||
_ = Task.Run(() => HandleRequest(context));
|
||||
}
|
||||
catch (HttpListenerException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleRequest(HttpListenerContext context)
|
||||
{
|
||||
if (context.Request.Url?.AbsolutePath.Equals("/fetchpackage", StringComparison.OrdinalIgnoreCase) == true)
|
||||
{
|
||||
string? indexStr = context.Request.QueryString["index"];
|
||||
if (indexStr != null && long.TryParse(indexStr, out long index))
|
||||
{
|
||||
var data = _getData(index);
|
||||
if (data != null)
|
||||
{
|
||||
_writeResponse(data, context.Response);
|
||||
}
|
||||
else
|
||||
{
|
||||
var responseText = JsonSerializer.Serialize(new { error = "Data not found" });
|
||||
context.Response.StatusCode = 404;
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(responseText);
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.ContentLength64 = buffer.Length;
|
||||
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
byte[] buffer = Encoding.UTF8.GetBytes("Invalid or missing 'index' parameter.");
|
||||
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = 404;
|
||||
byte[] buffer = Encoding.UTF8.GetBytes("Not Found");
|
||||
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
context.Response.OutputStream.Close();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"HTTP: [{string.Join(", ", _listener.Prefixes)}]";
|
||||
}
|
||||
}
|
||||
|
||||
8
Server/IServer.cs
Normal file
8
Server/IServer.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace NetworkTest;
|
||||
|
||||
interface IServer
|
||||
{
|
||||
public void Start();
|
||||
public void Stop();
|
||||
|
||||
}
|
||||
111
Server/Program.cs
Normal file
111
Server/Program.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Domain;
|
||||
using Domain.Dto;
|
||||
using MessagePack;
|
||||
using NetworkTest;
|
||||
using Server;
|
||||
|
||||
if (args.Length < 2)
|
||||
{
|
||||
System.Console.WriteLine("Pass twp arg: test/http/tcp and json/bin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
var dataGenerator = new DataGenerator(generationInterval: TimeSpan.FromMilliseconds(1));
|
||||
|
||||
var protocol = args[0];
|
||||
var serialization = args[1];
|
||||
|
||||
if (protocol == "test")
|
||||
{
|
||||
int nullCount = 0;
|
||||
long index = 0;
|
||||
var sw = Stopwatch.StartNew();
|
||||
var lastMs = 0L;
|
||||
var lastIndex = 0L;
|
||||
var ms = 1000;
|
||||
|
||||
var json = serialization == "json";
|
||||
while (true)
|
||||
{
|
||||
var data = dataGenerator.GetPackage(index);
|
||||
if (data == null)
|
||||
{
|
||||
nullCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (json)
|
||||
{
|
||||
JsonData jsonData = new JsonData(data);
|
||||
var responseText = JsonSerializer.Serialize(jsonData);
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(responseText);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessagePackData msgPackData = new MessagePackData(data);
|
||||
byte[] buffer = MessagePackSerializer.Serialize(msgPackData);
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
var diff = sw.ElapsedMilliseconds - lastMs;
|
||||
if (diff >= ms)
|
||||
{
|
||||
var serializrd = index - lastIndex;
|
||||
System.Console.WriteLine($"Serialized {serializrd} data packages in {diff} ms.");
|
||||
lastIndex = index;
|
||||
lastMs = sw.ElapsedMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IServer? server = protocol == "http" ?
|
||||
new HttpServer(index => dataGenerator.GetPackage(index),
|
||||
serialization == "json" ? PrepareResponseJson : PrepareResponseMessagePack) :
|
||||
null;
|
||||
|
||||
server?.Start();
|
||||
System.Console.WriteLine("Server started:");
|
||||
System.Console.WriteLine(server);
|
||||
|
||||
// Обработка выхода по Ctrl+C
|
||||
Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = true; // Prevent immediate termination
|
||||
Console.WriteLine("Shutdown signal received. Stopping server...");
|
||||
server?.Stop();
|
||||
Console.WriteLine("Goodbye!");
|
||||
Environment.Exit(0);
|
||||
};
|
||||
|
||||
|
||||
// Бесконечный цикл ожидания
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
|
||||
void PrepareResponseJson(Data data, HttpListenerResponse response)
|
||||
{
|
||||
JsonData jsonData = new JsonData(data);
|
||||
var responseText = JsonSerializer.Serialize(jsonData);
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(responseText);
|
||||
response.ContentType = "application/json";
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
void PrepareResponseMessagePack(Data data, HttpListenerResponse response)
|
||||
{
|
||||
MessagePackData msgPackData = new MessagePackData(data);
|
||||
byte[] buffer = MessagePackSerializer.Serialize(msgPackData);
|
||||
response.ContentType = "application/x-msgpack";
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
18
Server/Server.csproj
Normal file
18
Server/Server.csproj
Normal file
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Domain/Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MessagePack" Version="3.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user