Files
a301_mmo_game_server/ClientTester/EchoClientTester/Program.cs

258 lines
9.1 KiB
C#

using ClientTester.DummyService;
using ClientTester.EchoDummyService;
using ClientTester.StressTest;
using ClientTester.Utils;
using Serilog;
class EcoClientTester
{
public static string SERVER_IP = "localhost";
public static int SERVER_PORT = 9500;
public static readonly string CONNECTION_KEY = "test";
public static int CLIENT_COUNT = 100;
private async Task StartEchoDummyTest()
{
try
{
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) =>
{
e.Cancel = true;
Log.Warning("[SHUTDOWN] Ctrl+C 감지, 종료 중...");
cts.Cancel();
};
EchoDummyClientService service =
new EchoDummyClientService(CLIENT_COUNT, SERVER_IP, SERVER_PORT, CONNECTION_KEY, 100);
service.OnAllDisconnected += () =>
{
Log.Warning("[SHUTDOWN] 종료 이벤트 발생, 종료 중...");
cts.Cancel();
};
// service.IsTest = true;
// service.TestCount = 100;
await service.RunAsync(cts.Token);
service.PrintStats();
service.Stop();
await Log.CloseAndFlushAsync();
}
catch (Exception e)
{
Log.Error($"[SHUTDOWN] 예외 발생 : {e}");
}
}
private async Task StartDummyTest()
{
try
{
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) =>
{
e.Cancel = true;
Log.Warning("[SHUTDOWN] Ctrl+C 감지, 종료 중...");
cts.Cancel();
};
DummyClientService service =
new DummyClientService(CLIENT_COUNT, SERVER_IP, SERVER_PORT, CONNECTION_KEY, 100);
service.OnAllDisconnected += () =>
{
Log.Warning("[SHUTDOWN] 종료 이벤트 발생, 종료 중...");
cts.Cancel();
};
await service.RunAsync(cts.Token);
service.PrintStats();
service.Stop();
await Log.CloseAndFlushAsync();
}
catch (Exception e)
{
Log.Error($"[SHUTDOWN] 예외 발생 : {e}");
}
}
private async Task StartStressTest(int duration, int sendInterval, int rampInterval, int clientsPerRamp)
{
try
{
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) =>
{
e.Cancel = true;
Log.Warning("[SHUTDOWN] Ctrl+C 감지, 종료 중...");
cts.Cancel();
};
StressTestService service = new StressTestService(
CLIENT_COUNT, SERVER_IP, SERVER_PORT, CONNECTION_KEY,
durationSec: duration,
sendIntervalMs: sendInterval,
rampUpIntervalMs: rampInterval,
clientsPerRamp: clientsPerRamp);
service.OnTestCompleted += () =>
{
Log.Information("[STRESS] 테스트 시간 종료.");
};
try
{
await service.RunAsync(cts.Token);
}
catch (OperationCanceledException) { }
service.PrintFinalReport();
string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
string csvPath = $"results/stress_{CLIENT_COUNT}clients_{timestamp}.csv";
Directory.CreateDirectory("results");
service.ExportCsv(csvPath);
service.Stop();
await Log.CloseAndFlushAsync();
}
catch (Exception e)
{
Log.Error($"[SHUTDOWN] 예외 발생 : {e}");
}
}
private static void PrintUsage()
{
Console.WriteLine();
Console.WriteLine("사용법:");
Console.WriteLine(" EchoClientTester 대화형 모드");
Console.WriteLine(" EchoClientTester stress [옵션] 스트레스 테스트");
Console.WriteLine();
Console.WriteLine("스트레스 테스트 옵션:");
Console.WriteLine(" -c, --clients <수> 클라이언트 수 (기본: 50)");
Console.WriteLine(" -d, --duration <초> 테스트 시간 (기본: 60, 0=무제한)");
Console.WriteLine(" -i, --interval <ms> 전송 주기 (기본: 100)");
Console.WriteLine(" -r, --ramp <ms> Ramp-up 간격 (기본: 1000)");
Console.WriteLine(" -b, --batch <수> Ramp-up 당 클라이언트 수 (기본: 10)");
Console.WriteLine(" --ip <주소> 서버 IP (기본: localhost)");
Console.WriteLine(" --port <포트> 서버 포트 (기본: 9500)");
Console.WriteLine();
Console.WriteLine("예시:");
Console.WriteLine(" EchoClientTester stress -c 100 -d 120");
Console.WriteLine(" EchoClientTester stress -c 200 -d 60 -r 500 -b 20 --ip 192.168.0.10");
}
private static async Task Main(string[] args)
{
// 유니코드 문자(═, ║ 등) 콘솔 깨짐 방지
Console.OutputEncoding = System.Text.Encoding.UTF8;
// 크래시 덤프 핸들러 (Release: .log + .dmp / Debug: .log)
CrashDumpHandler.Register();
// .MinimumLevel.Warning() // Warning 이상만 출력 배포시
string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File($"logs2/log_{timestamp}.txt")
.CreateLogger();
EcoClientTester tester = new EcoClientTester();
// CLI 모드: stress 명령
if (args.Length > 0 && args[0].Equals("stress", StringComparison.OrdinalIgnoreCase))
{
// 기본값
CLIENT_COUNT = 50;
int duration = 60;
int sendInterval = 100;
int rampInterval = 1000;
int clientsPerRamp = 10;
for (int i = 1; i < args.Length; i++)
{
switch (args[i])
{
case "-c": case "--clients":
if (i + 1 < args.Length) CLIENT_COUNT = int.Parse(args[++i]);
break;
case "-d": case "--duration":
if (i + 1 < args.Length) duration = int.Parse(args[++i]);
break;
case "-i": case "--interval":
if (i + 1 < args.Length) sendInterval = int.Parse(args[++i]);
break;
case "-r": case "--ramp":
if (i + 1 < args.Length) rampInterval = int.Parse(args[++i]);
break;
case "-b": case "--batch":
if (i + 1 < args.Length) clientsPerRamp = int.Parse(args[++i]);
break;
case "--ip":
if (i + 1 < args.Length) SERVER_IP = args[++i];
break;
case "--port":
if (i + 1 < args.Length) SERVER_PORT = int.Parse(args[++i]);
break;
case "-h": case "--help":
PrintUsage();
return;
}
}
await tester.StartStressTest(duration, sendInterval, rampInterval, clientsPerRamp);
return;
}
// CLI 모드: help
if (args.Length > 0 && (args[0] == "-h" || args[0] == "--help"))
{
PrintUsage();
return;
}
// 대화형 모드 (기존)
Log.Information("========== 더미 클라 테스터 ==========");
Log.Information("1. 에코 서버");
Log.Information("2. 더미 클라(이동만)");
Log.Information("3. 스트레스 테스트 (부하)");
Log.Information("====================================");
Log.Information("1 / 2 / 3 : ");
string? input = Console.ReadLine();
if (!int.TryParse(input, out int choice) || choice < 1 || choice > 3)
{
Log.Warning("1, 2, 3 중 입력하세요.");
return;
}
if (choice == 1)
{
await tester.StartEchoDummyTest();
}
else if (choice == 2)
{
await tester.StartDummyTest();
}
else if (choice == 3)
{
// 대화형 스트레스 테스트 설정
Log.Information("클라이언트 수 (기본 50): ");
string? countInput = Console.ReadLine();
CLIENT_COUNT = string.IsNullOrEmpty(countInput) ? 50 : int.Parse(countInput);
Log.Information("테스트 시간(초) (기본 60, 0=무제한): ");
string? durInput = Console.ReadLine();
int dur = string.IsNullOrEmpty(durInput) ? 60 : int.Parse(durInput);
await tester.StartStressTest(dur, 100, 1000, 10);
}
}
}