Добавлен предсказуемый генератор данных
This commit is contained in:
30
.vscode/launch.json
vendored
30
.vscode/launch.json
vendored
@@ -6,7 +6,7 @@
|
|||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
||||||
"args": [ "http", "json" ],
|
"args": [ "http", "json", "random" ],
|
||||||
"cwd": "${workspaceFolder}/Server",
|
"cwd": "${workspaceFolder}/Server",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
||||||
"args": [ "http", "bin" ],
|
"args": [ "http", "bin", "random" ],
|
||||||
"cwd": "${workspaceFolder}/Server",
|
"cwd": "${workspaceFolder}/Server",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
||||||
"args": [ "tcp", "json" ],
|
"args": [ "tcp", "json", "random" ],
|
||||||
"cwd": "${workspaceFolder}/Server",
|
"cwd": "${workspaceFolder}/Server",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
||||||
"args": [ "tcp", "bin" ],
|
"args": [ "tcp", "bin", "random" ],
|
||||||
"cwd": "${workspaceFolder}/Server",
|
"cwd": "${workspaceFolder}/Server",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
@@ -105,7 +105,21 @@
|
|||||||
"presentation": {
|
"presentation": {
|
||||||
"hidden": true
|
"hidden": true
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "TCP/BIN (Predictable) Server",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/Server/bin/Debug/net8.0/Server.dll",
|
||||||
|
"args": [ "tcp", "bin", "predictable", "2000" ],
|
||||||
|
"cwd": "${workspaceFolder}/Server",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"presentation": {
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"compounds": [
|
"compounds": [
|
||||||
{
|
{
|
||||||
@@ -132,6 +146,12 @@
|
|||||||
"configurations": ["TCP/BIN Server", "TCP/BIN Client"],
|
"configurations": ["TCP/BIN Server", "TCP/BIN Client"],
|
||||||
"preLaunchTask": "dotnet: build",
|
"preLaunchTask": "dotnet: build",
|
||||||
"stopAll": true
|
"stopAll": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TCP/BIN: (Predictable) Server and Client",
|
||||||
|
"configurations": ["TCP/BIN (Predictable) Server", "TCP/BIN Client"],
|
||||||
|
"preLaunchTask": "dotnet: build",
|
||||||
|
"stopAll": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ public class TcpClientWrapper : IClient
|
|||||||
Console.WriteLine($"Error: {ex.Message}");
|
Console.WriteLine($"Error: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.Console.WriteLine("End cycle");
|
|
||||||
}
|
}
|
||||||
|
System.Console.WriteLine("End ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ namespace Domain.Dto;
|
|||||||
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
// Вообще то этот класс не следует размещать в Domain, но я не захотел дублировать его в двух проектах по соседству
|
||||||
public class JsonData
|
public class JsonData
|
||||||
{
|
{
|
||||||
[JsonPropertyName("concentrationIndex")]
|
[JsonPropertyName("concentrationIndex")]
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ namespace Domain.Dto;
|
|||||||
|
|
||||||
using MessagePack;
|
using MessagePack;
|
||||||
|
|
||||||
|
|
||||||
|
// Вообще то этот класс не следует размещать в Domain, но я не захотел дублировать его в двух проектах по соседству
|
||||||
[MessagePackObject]
|
[MessagePackObject]
|
||||||
public class MessagePackData
|
public class MessagePackData
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
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, "ALL");
|
|
||||||
_cache.AddLast(firstData);
|
|
||||||
_dict[firstData.FrameIndex] = firstData;
|
|
||||||
|
|
||||||
while (!token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
//await Task.Delay(_generationInterval, token);
|
|
||||||
var first = _cache.First!.Value;
|
|
||||||
var last = _cache.Last!.Value;
|
|
||||||
if (last.FrameIndex - _maxRequestedIndex < _minNewPackages)
|
|
||||||
{
|
|
||||||
var data = GenerateRandomData(last.FrameIndex + 1, "ALL");
|
|
||||||
_cache.AddLast(data);
|
|
||||||
_dict[data.FrameIndex] = data;
|
|
||||||
}
|
|
||||||
if (_maxRequestedIndex - first.FrameIndex > _maxPreviousPackages)
|
|
||||||
{
|
|
||||||
_cache.RemoveFirst();
|
|
||||||
_dict.TryRemove(first.FrameIndex, 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 frameIndex, string overlayPoint)
|
|
||||||
{
|
|
||||||
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() < 0.1 ? null : _random.NextDouble(),
|
|
||||||
RelaxationIndex: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
|
||||||
CognitiveControl: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
|
||||||
CognitiveLoad: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
|
||||||
Alpha: _random.NextDouble() < 0.1 ? null : alpha,
|
|
||||||
Beta: _random.NextDouble() < 0.1 ? null : beta,
|
|
||||||
Theta: _random.NextDouble() < 0.1 ? null : theta,
|
|
||||||
Smr: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
|
||||||
MuWave: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
|
||||||
OverlayPoint: overlayPoint,
|
|
||||||
Artifact: _random.NextDouble() < 0.1 ? null : signalQuality < 0.5,
|
|
||||||
SignalQuality: _random.NextDouble() < 0.1 ? null : signalQuality,
|
|
||||||
FrameIndex: frameIndex,
|
|
||||||
TimeOfDataGenerate: _random.NextDouble() < 0.1 ? null : DateTime.Now
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
Server/DataGenerator/IDataGenerator.cs
Normal file
18
Server/DataGenerator/IDataGenerator.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Domain;
|
||||||
|
|
||||||
|
namespace Server.DataGenerator;
|
||||||
|
|
||||||
|
interface IDataGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получить следующий пакет (если вызывающий код не умеет работать с фреймами, его следует закешировать и выдавать по пакетно)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Data GetPackage();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить новый фрейм данных
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Data[] GetFrame();
|
||||||
|
}
|
||||||
80
Server/DataGenerator/PredictableDataGenerator.cs
Normal file
80
Server/DataGenerator/PredictableDataGenerator.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Domain;
|
||||||
|
|
||||||
|
namespace Server.DataGenerator;
|
||||||
|
|
||||||
|
public class PredictableDataGenerator : IDataGenerator
|
||||||
|
{
|
||||||
|
private long _currentFrameIndex = 0;
|
||||||
|
private Data[] _currentFrame;
|
||||||
|
private int _currentPackageInFrame = 0;
|
||||||
|
private DateTime _lastFrameTime;
|
||||||
|
private bool _frameArtifact = false;
|
||||||
|
private int _delay;
|
||||||
|
|
||||||
|
public PredictableDataGenerator(int frameDelay = 0)
|
||||||
|
{
|
||||||
|
_delay = frameDelay;
|
||||||
|
_lastFrameTime = DateTime.Now;
|
||||||
|
_currentFrame = GenerateFrame(0, _lastFrameTime, _frameArtifact);
|
||||||
|
_currentFrameIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Data[] GenerateFrame(long frameIndex, DateTime frameTime, bool artifact)
|
||||||
|
{
|
||||||
|
Thread.Sleep(_delay);
|
||||||
|
var overlayPoints = OverlayPoints.Points.Take(8).Append(OverlayPoints.All).ToArray();
|
||||||
|
return overlayPoints.Select((op, idx) => GeneratePredictableData(frameIndex, op, idx, frameTime, artifact)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Data GeneratePredictableData(long frameIndex, string overlayPoint, int index, DateTime frameTime, bool artifact)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
if (overlayPoint == OverlayPoints.All)
|
||||||
|
{
|
||||||
|
value = frameIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = 1000 * (index + 1) + frameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Data(
|
||||||
|
ConcentrationIndex: value,
|
||||||
|
RelaxationIndex: value,
|
||||||
|
CognitiveControl: value,
|
||||||
|
CognitiveLoad: value,
|
||||||
|
Alpha: value,
|
||||||
|
Beta: value,
|
||||||
|
Theta: value,
|
||||||
|
Smr: value,
|
||||||
|
MuWave: value,
|
||||||
|
OverlayPoint: overlayPoint,
|
||||||
|
Artifact: artifact,
|
||||||
|
SignalQuality: value,
|
||||||
|
FrameIndex: frameIndex,
|
||||||
|
TimeOfDataGenerate: frameTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data GetPackage()
|
||||||
|
{
|
||||||
|
if (_currentPackageInFrame >= _currentFrame.Length)
|
||||||
|
{
|
||||||
|
_frameArtifact = !_frameArtifact;
|
||||||
|
_lastFrameTime = _lastFrameTime.AddSeconds(1);
|
||||||
|
_currentFrame = GenerateFrame(Interlocked.Increment(ref _currentFrameIndex), _lastFrameTime, _frameArtifact);
|
||||||
|
_currentPackageInFrame = 0;
|
||||||
|
}
|
||||||
|
return _currentFrame[_currentPackageInFrame++];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data[] GetFrame()
|
||||||
|
{
|
||||||
|
_frameArtifact = !_frameArtifact;
|
||||||
|
_lastFrameTime = _lastFrameTime.AddSeconds(1);
|
||||||
|
return GenerateFrame(Interlocked.Increment(ref _currentFrameIndex), _lastFrameTime, _frameArtifact);
|
||||||
|
}
|
||||||
|
}
|
||||||
67
Server/DataGenerator/RandomDataGenerator.cs
Normal file
67
Server/DataGenerator/RandomDataGenerator.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Domain;
|
||||||
|
|
||||||
|
namespace Server.DataGenerator;
|
||||||
|
|
||||||
|
public class RandomDataGenerator : IDataGenerator
|
||||||
|
{
|
||||||
|
private static readonly Random _random = new Random();
|
||||||
|
|
||||||
|
private long _currentFrameIndex = 0;
|
||||||
|
private Data[] _currentFrame;
|
||||||
|
private int _currentPackageInFrame = 0;
|
||||||
|
|
||||||
|
public RandomDataGenerator(int minNewPackages = 50, int maxPreviousPackages = 50, TimeSpan? generationInterval = null)
|
||||||
|
{
|
||||||
|
_currentFrame = GenerateFrame(0);
|
||||||
|
_currentFrameIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Data[] GenerateFrame(long frameIndex)
|
||||||
|
{
|
||||||
|
var overlayPoints = OverlayPoints.Points.Take(8).Append(OverlayPoints.All).ToArray();
|
||||||
|
return overlayPoints.Select(op => GenerateRandomData(frameIndex, op)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Data GenerateRandomData(long frameIndex, string overlayPoint)
|
||||||
|
{
|
||||||
|
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() < 0.1 ? null : _random.NextDouble(),
|
||||||
|
RelaxationIndex: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
||||||
|
CognitiveControl: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
||||||
|
CognitiveLoad: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
||||||
|
Alpha: _random.NextDouble() < 0.1 ? null : alpha,
|
||||||
|
Beta: _random.NextDouble() < 0.1 ? null : beta,
|
||||||
|
Theta: _random.NextDouble() < 0.1 ? null : theta,
|
||||||
|
Smr: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
||||||
|
MuWave: _random.NextDouble() < 0.1 ? null : _random.NextDouble(),
|
||||||
|
OverlayPoint: overlayPoint,
|
||||||
|
Artifact: _random.NextDouble() < 0.1 ? null : signalQuality < 0.5,
|
||||||
|
SignalQuality: _random.NextDouble() < 0.1 ? null : signalQuality,
|
||||||
|
FrameIndex: frameIndex,
|
||||||
|
TimeOfDataGenerate: _random.NextDouble() < 0.1 ? null : DateTime.Now
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data GetPackage()
|
||||||
|
{
|
||||||
|
if (_currentPackageInFrame >= _currentFrame.Length)
|
||||||
|
{
|
||||||
|
_currentFrame = GenerateFrame(Interlocked.Increment(ref _currentFrameIndex));
|
||||||
|
_currentPackageInFrame = 0;
|
||||||
|
}
|
||||||
|
return _currentFrame[_currentPackageInFrame++];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data[] GetFrame()
|
||||||
|
{
|
||||||
|
return GenerateFrame(Interlocked.Increment(ref _currentFrameIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,12 +14,12 @@ public class HttpServer : IServer
|
|||||||
private readonly HttpListener _listener;
|
private readonly HttpListener _listener;
|
||||||
private readonly string _url;
|
private readonly string _url;
|
||||||
private CancellationTokenSource _cts = new CancellationTokenSource();
|
private CancellationTokenSource _cts = new CancellationTokenSource();
|
||||||
private Func<long, Data?> _getData;
|
private Func<Data?> _getPackage;
|
||||||
private Action<Data, HttpListenerResponse> _writeResponse;
|
private Action<Data, HttpListenerResponse> _writeResponse;
|
||||||
|
|
||||||
public HttpServer(Func<long, Data?> getData, Action<Data, HttpListenerResponse> writeResponse, string url = "http://*:5555/")
|
public HttpServer(Func<Data?> getPackage, Action<Data, HttpListenerResponse> writeResponse, string url = "http://*:5555/")
|
||||||
{
|
{
|
||||||
_getData = getData;
|
_getPackage = getPackage;
|
||||||
_writeResponse = writeResponse;
|
_writeResponse = writeResponse;
|
||||||
_url = url;
|
_url = url;
|
||||||
_listener = new HttpListener();
|
_listener = new HttpListener();
|
||||||
@@ -63,28 +63,18 @@ public class HttpServer : IServer
|
|||||||
{
|
{
|
||||||
if (context.Request.Url?.AbsolutePath.Equals("/fetchpackage", StringComparison.OrdinalIgnoreCase) == true)
|
if (context.Request.Url?.AbsolutePath.Equals("/fetchpackage", StringComparison.OrdinalIgnoreCase) == true)
|
||||||
{
|
{
|
||||||
string? indexStr = context.Request.QueryString["index"];
|
var data = _getPackage();
|
||||||
if (indexStr != null && long.TryParse(indexStr, out long index))
|
if (data != null)
|
||||||
{
|
{
|
||||||
var data = _getData(index);
|
_writeResponse(data, context.Response);
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = 400;
|
var responseText = JsonSerializer.Serialize(new { error = "Data not found" });
|
||||||
byte[] buffer = Encoding.UTF8.GetBytes("Invalid or missing 'index' parameter.");
|
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);
|
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,34 @@ using Domain.Dto;
|
|||||||
using MessagePack;
|
using MessagePack;
|
||||||
using NetworkTest;
|
using NetworkTest;
|
||||||
using Server;
|
using Server;
|
||||||
|
using Server.DataGenerator;
|
||||||
|
|
||||||
if (args.Length < 2)
|
if (args.Length < 3)
|
||||||
{
|
{
|
||||||
System.Console.WriteLine("Pass twp arg: test/http/tcp and json/bin");
|
System.Console.WriteLine("Pass three args: test/http/tcp, json/bin, and random/predictable");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataGenerator = new DataGenerator(generationInterval: TimeSpan.FromMilliseconds(1));
|
|
||||||
|
|
||||||
var protocol = args[0];
|
var protocol = args[0];
|
||||||
var serialization = args[1];
|
var serialization = args[1];
|
||||||
|
var generatorType = args[2];
|
||||||
|
int delay = 0;
|
||||||
|
|
||||||
|
if (generatorType == "predictable" && args.Length > 3)
|
||||||
|
{
|
||||||
|
if (!int.TryParse(args[3], out delay))
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Invalid delay value. Must be an integer.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IDataGenerator dataGenerator = generatorType switch
|
||||||
|
{
|
||||||
|
"random" => new RandomDataGenerator(generationInterval: TimeSpan.FromMilliseconds(1)),
|
||||||
|
"predictable" => new PredictableDataGenerator(delay),
|
||||||
|
_ => throw new ArgumentException("Generator type must be 'random' or 'predictable'")
|
||||||
|
};
|
||||||
|
|
||||||
if (protocol == "test")
|
if (protocol == "test")
|
||||||
{
|
{
|
||||||
@@ -31,7 +48,7 @@ if (protocol == "test")
|
|||||||
var json = serialization == "json";
|
var json = serialization == "json";
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var data = dataGenerator.GetPackage(index);
|
var data = dataGenerator.GetPackage();
|
||||||
if (data == null)
|
if (data == null)
|
||||||
{
|
{
|
||||||
nullCount++;
|
nullCount++;
|
||||||
@@ -65,9 +82,9 @@ if (protocol == "test")
|
|||||||
|
|
||||||
IServer? server = protocol switch
|
IServer? server = protocol switch
|
||||||
{
|
{
|
||||||
"http" => new HttpServer(index => dataGenerator.GetPackage(index),
|
"http" => new HttpServer(() => dataGenerator.GetPackage(),
|
||||||
serialization == "json" ? PrepareResponseJson : PrepareResponseMessagePack),
|
serialization == "json" ? PrepareResponseJson : PrepareResponseMessagePack),
|
||||||
"tcp" => new TcpServer(index => dataGenerator.GetPackage(index),
|
"tcp" => new TcpServer(() => dataGenerator.GetPackage(),
|
||||||
serialization == "json" ? PrepareBytesJson : PrepareBytesMessagePack),
|
serialization == "json" ? PrepareBytesJson : PrepareBytesMessagePack),
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ public class TcpServer : IServer
|
|||||||
{
|
{
|
||||||
private const uint MagicHeader = 0xDEADBEEF;
|
private const uint MagicHeader = 0xDEADBEEF;
|
||||||
private readonly TcpListener _listener;
|
private readonly TcpListener _listener;
|
||||||
private readonly Func<long, Data?> _getData;
|
private readonly Func<Data?> _getPackage;
|
||||||
private readonly Func<Data, byte[]> _prepareBytes;
|
private readonly Func<Data, byte[]> _prepareBytes;
|
||||||
private readonly int _port;
|
private readonly int _port;
|
||||||
private CancellationTokenSource _cts = new CancellationTokenSource();
|
private CancellationTokenSource _cts = new CancellationTokenSource();
|
||||||
|
|
||||||
public TcpServer(Func<long, Data?> getData, Func<Data, byte[]> prepareBytes, int port = 5555)
|
public TcpServer(Func<Data?> getPackage, Func<Data, byte[]> prepareBytes, int port = 5555)
|
||||||
{
|
{
|
||||||
_getData = getData;
|
_getPackage = getPackage;
|
||||||
_prepareBytes = prepareBytes;
|
_prepareBytes = prepareBytes;
|
||||||
_port = port;
|
_port = port;
|
||||||
_listener = new TcpListener(IPAddress.Any, _port);
|
_listener = new TcpListener(IPAddress.Any, _port);
|
||||||
@@ -63,10 +63,9 @@ public class TcpServer : IServer
|
|||||||
using (client)
|
using (client)
|
||||||
using (var stream = client.GetStream())
|
using (var stream = client.GetStream())
|
||||||
{
|
{
|
||||||
var index = 0L;
|
|
||||||
while (!token.IsCancellationRequested && client.Connected)
|
while (!token.IsCancellationRequested && client.Connected)
|
||||||
{
|
{
|
||||||
var data = _getData(index);
|
var data = _getPackage();
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
var bytes = _prepareBytes(data);
|
var bytes = _prepareBytes(data);
|
||||||
@@ -75,7 +74,6 @@ public class TcpServer : IServer
|
|||||||
await stream.WriteAsync(magicBytes, 0, magicBytes.Length, token);
|
await stream.WriteAsync(magicBytes, 0, magicBytes.Length, token);
|
||||||
await stream.WriteAsync(lengthBytes, 0, lengthBytes.Length, token);
|
await stream.WriteAsync(lengthBytes, 0, lengthBytes.Length, token);
|
||||||
await stream.WriteAsync(bytes, 0, bytes.Length, token);
|
await stream.WriteAsync(bytes, 0, bytes.Length, token);
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
// await Task.Delay(50, token); // Removed delay to test maximum throughput
|
// await Task.Delay(50, token); // Removed delay to test maximum throughput
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user