using LiteNetLib.Utils; using Serilog; namespace ClientTester.EchoDummyService; public class DummyClientService { private readonly List _clients; private readonly int _sendInterval; public DummyClientService(int count, string ip, int port, string key, int sendIntervalMs = 1000) { _sendInterval = sendIntervalMs; _clients = Enumerable.Range(0, count) .Select(i => new DummyClients(i, ip, port, key)) .ToList(); Log.Information("[SERVICE] {Count}개 클라이언트 생성 → {Ip}:{Port}", count, ip, port); } public async Task RunAsync(CancellationToken ct) { await Task.WhenAll( PollLoopAsync(ct), SendLoopAsync(ct) ); } private async Task PollLoopAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { foreach (var c in _clients) c.PollEvents(); try { await Task.Delay(15, ct); } catch (OperationCanceledException) { break; } } } private async Task SendLoopAsync(CancellationToken ct) { try { await Task.Delay(500, ct); } catch (OperationCanceledException) { return; } int tick = 0; while (!ct.IsCancellationRequested) { int sent = 0; foreach (var client in _clients) { client.SendPing(); if (client.Peer != null) sent++; } Log.Information("[TICK {Tick:000}] {Sent}/{Total} 전송", tick, sent, _clients.Count); tick++; try { await Task.Delay(_sendInterval, ct); } catch (OperationCanceledException) { break; } } } public void PrintStats() { int totalSent = 0, totalRecv = 0; int connected = 0; Log.Information("════════════ Performance Report ════════════"); double totalAvgRtt = 0; foreach (var c in _clients) { var stats = c.Peer?.Statistics; long loss = stats?.PacketLoss ?? 0; float lossPct = stats?.PacketLossPercent ?? 0f; Log.Information( "[Client {ClientId:00}] Sent={Sent} Recv={Recv} | Loss={Loss}({LossPct:F1}%) AvgRTT={AvgRtt:F3}ms LastRTT={LastRtt:F3}ms", c.ClientId, c.SentCount, c.ReceivedCount, loss, lossPct, c.AvgRttMs, c.LastRttMs); totalSent += c.SentCount; totalRecv += c.ReceivedCount; totalAvgRtt += c.AvgRttMs; if (c.Peer != null) connected++; } double avgRtt = connected > 0 ? totalAvgRtt / connected : 0; Log.Information("────────────────────────────────────────────"); Log.Information( "[TOTAL] Sent={Sent} Recv={Recv} Connected={Connected}/{Total} AvgRTT={AvgRtt:F3}ms", totalSent, totalRecv, connected, _clients.Count, avgRtt); Log.Information("════════════════════════════════════════════"); } public void Stop() { foreach (var c in _clients) c.Stop(); Log.Information("[SERVICE] 모든 클라이언트 종료됨."); } }