change exit mode

This commit is contained in:
ascet-tomsk
2026-01-18 01:58:54 +07:00
parent be23f56867
commit 759916ff57
3 changed files with 53 additions and 35 deletions

View File

@@ -2,7 +2,7 @@
"profiles": { "profiles": {
"f-cln": { "f-cln": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "--port 3113 -i 172.22.176.1" "commandLineArgs": "-p 1771"
} }
} }
} }

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>f_cln</RootNamespace> <RootNamespace>f_cln</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>

View File

@@ -20,7 +20,7 @@ namespace f_srv
Option<IPAddress> ipOption = new("address", new[] { "--ip", "-i" }) Option<IPAddress> ipOption = new("address", new[] { "--ip", "-i" })
{ {
Description = "IP адрес для прослушивания (по умолчанию: все интерфейсы)", Description = "IP адрес для прослушивания (по умолчанию: все интерфейсы)",
DefaultValueFactory = parseResult => IPAddress.Any, DefaultValueFactory = parseResult => IPAddress.Any,
CustomParser = result => CustomParser = result =>
{ {
if (result.Tokens.Count != 1) if (result.Tokens.Count != 1)
@@ -80,41 +80,59 @@ namespace f_srv
// Запускаем сервер в отдельной задаче // Запускаем сервер в отдельной задаче
var serverTask = Task.Run(() => StartServer(ip, port, _cancellationTokenSource.Token)); var serverTask = Task.Run(() => StartServer(ip, port, _cancellationTokenSource.Token));
// Ожидаем нажатие клавиши с явной обработкой Console.WriteLine("Сервер запущен. Введите 'Exit' для остановки...");
Console.WriteLine("Сервер запущен. Нажмите любую клавишу для остановки...");
// Ждем ввод строки "Exit" в отдельном потоке
// Ждем нажатия клавиши в отдельном потоке var exitTask = Task.Run(() =>
var keyTask = Task.Run(() =>
{ {
Console.ReadKey(true); // true - не отображать нажатую клавишу while (!_cancellationTokenSource.IsCancellationRequested)
return true; {
var input = Console.ReadLine();
if (!string.IsNullOrEmpty(input) &&
input.Trim().Equals("Exit", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}); });
// Ожидаем либо нажатия клавиши, либо завершения сервера // Ожидаем либо ввод "Exit", либо завершение сервера
await Task.WhenAny(serverTask, keyTask); var completedTask = await Task.WhenAny(serverTask, exitTask);
if (!_cancellationTokenSource.IsCancellationRequested) if (completedTask == exitTask && exitTask.Result)
{ {
// Отправляем сигнал отмены // Пользователь ввел Exit
_cancellationTokenSource.Cancel(); if (!_cancellationTokenSource.IsCancellationRequested)
// Останавливаем listener
_listener?.Stop();
// Даем серверу время на корректное завершение
try
{ {
await Task.WhenAny(serverTask, Task.Delay(2000)); Console.WriteLine("Остановка сервера...");
_cancellationTokenSource.Cancel();
_listener?.Stop();
// Даем серверу время на корректное завершение
try
{
await Task.WhenAny(serverTask, Task.Delay(2000));
}
catch
{
// Игнорируем исключения при завершении
}
Console.WriteLine("Сервер остановлен.");
} }
catch
{
// Игнорируем исключения при завершении
}
Console.WriteLine("Сервер остановлен.");
} }
else
{
// Сервер завершился сам (ошибка или другая причина)
if (!_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Cancel();
}
Console.WriteLine("Сервер завершил работу.");
}
return 0; return 0;
} }
else else
@@ -146,11 +164,11 @@ namespace f_srv
// Ожидание подключения клиента с таймаутом для проверки отмены // Ожидание подключения клиента с таймаутом для проверки отмены
var acceptTask = _listener.AcceptTcpClientAsync(); var acceptTask = _listener.AcceptTcpClientAsync();
var completedTask = await Task.WhenAny(acceptTask, Task.Delay(1000, cancellationToken)); var completedTask = await Task.WhenAny(acceptTask, Task.Delay(1000, cancellationToken));
if (completedTask == acceptTask && !cancellationToken.IsCancellationRequested) if (completedTask == acceptTask && !cancellationToken.IsCancellationRequested)
{ {
var client = await acceptTask; var client = await acceptTask;
// Обработка клиента в отдельной задаче // Обработка клиента в отдельной задаче
_ = Task.Run(async () => await HandleClient(client, cancellationToken)); _ = Task.Run(async () => await HandleClient(client, cancellationToken));
} }
@@ -212,7 +230,7 @@ namespace f_srv
{ {
// Чтение строки (до символа новой строки) // Чтение строки (до символа новой строки)
var line = await reader.ReadLineAsync(); var line = await reader.ReadLineAsync();
if (line == null) if (line == null)
{ {
// Клиент отключился // Клиент отключился