89 lines
2.6 KiB
C#
89 lines
2.6 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Domain;
|
|
|
|
namespace NetworkTest;
|
|
|
|
public class TcpServer : IServer
|
|
{
|
|
private const uint MagicHeader = 0xDEADBEEF;
|
|
private readonly TcpListener _listener;
|
|
private readonly Func<long, Data?> _getData;
|
|
private readonly Func<Data, byte[]> _prepareBytes;
|
|
private readonly int _port;
|
|
private CancellationTokenSource _cts = new CancellationTokenSource();
|
|
|
|
public TcpServer(Func<long, Data?> getData, Func<Data, byte[]> prepareBytes, int port = 5555)
|
|
{
|
|
_getData = getData;
|
|
_prepareBytes = prepareBytes;
|
|
_port = port;
|
|
_listener = new TcpListener(IPAddress.Any, _port);
|
|
}
|
|
|
|
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 client = await _listener.AcceptTcpClientAsync(token);
|
|
_ = Task.Run(() => HandleClientAsync(client, token));
|
|
}
|
|
catch (SocketException)
|
|
{
|
|
break;
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task HandleClientAsync(TcpClient client, CancellationToken token)
|
|
{
|
|
using (client)
|
|
using (var stream = client.GetStream())
|
|
{
|
|
var index = 0L;
|
|
while (!token.IsCancellationRequested && client.Connected)
|
|
{
|
|
var data = _getData(index);
|
|
if (data != null)
|
|
{
|
|
var bytes = _prepareBytes(data);
|
|
var magicBytes = BitConverter.GetBytes(MagicHeader);
|
|
var lengthBytes = BitConverter.GetBytes(bytes.Length);
|
|
await stream.WriteAsync(magicBytes, 0, magicBytes.Length, token);
|
|
await stream.WriteAsync(lengthBytes, 0, lengthBytes.Length, token);
|
|
await stream.WriteAsync(bytes, 0, bytes.Length, token);
|
|
index++;
|
|
}
|
|
// await Task.Delay(50, token); // Removed delay to test maximum throughput
|
|
}
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"TcpServer listening on port {_port}";
|
|
}
|
|
} |