Files
LINUX/f-srv/Program.cs
2026-01-16 00:30:19 +07:00

206 lines
8.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.CommandLine;
using System.CommandLine.Parsing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace f_srv
{
class Program
{
private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private static TcpListener? _listener;
static async Task<int> Main(string[] args)
{
// Создание команды с аргументами
Option<IPAddress> ipOption = new("address", new[] { "--ip", "-i" })
{
Description = "IP адрес для прослушивания (по умолчанию: все интерфейсы)",
DefaultValueFactory = parseResult => IPAddress.Any
};
Option<int> portOption = new("port", new[] { "--port", "-p" })
{
Description = "Порт для прослушивания (по умолчанию: 1771)",
DefaultValueFactory = parseResult => 1771
};
var rootCommand = new RootCommand("Сервер для получения строк и отправки их в обратном порядке")
{
ipOption,
portOption
};
{
rootCommand.Parse("-h").Invoke();
rootCommand.Parse("--version").Invoke();
}
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.Errors.Count == 0)
{
IPAddress? ip = parseResult.GetValue(ipOption);
int port = parseResult.GetValue(portOption);
if (ip == null)
{
Console.Error.WriteLine("Ошибка: IP адрес не указан или имеет неверный формат");
return 2;
}
// Запускаем сервер в отдельной задаче
var serverTask = Task.Run(() => StartServer(ip, port, _cancellationTokenSource.Token));
// Ожидаем нажатие клавиши
Console.WriteLine("Сервер запущен. Нажмите любую клавишу для остановки...");
Console.ReadKey();
// Отправляем сигнал отмены
_cancellationTokenSource.Cancel();
// Останавливаем listener
_listener?.Stop();
// Ждем завершения сервера
await serverTask;
Console.WriteLine("Сервер остановлен.");
return 0;
}
else
{
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
}
}
static async Task StartServer(IPAddress ip, int port, CancellationToken cancellationToken)
{
try
{
Console.WriteLine($"Запуск сервера на {ip}:{port}");
// Создание TCP listener
_listener = new TcpListener(ip, port);
_listener.Start();
Console.WriteLine("Сервер запущен. Ожидание подключений...");
while (!cancellationToken.IsCancellationRequested)
{
try
{
// Ожидание подключения клиента с таймаутом для проверки отмены
var acceptTask = _listener.AcceptTcpClientAsync();
var completedTask = await Task.WhenAny(acceptTask, Task.Delay(1000, cancellationToken));
if (completedTask == acceptTask && !cancellationToken.IsCancellationRequested)
{
var client = await acceptTask;
// Обработка клиента в отдельной задаче
_ = Task.Run(async () => await HandleClient(client, cancellationToken));
}
}
catch (OperationCanceledException)
{
// Игнорируем отмену
}
catch (Exception ex)
{
if (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine($"Ошибка при принятии подключения: {ex.Message}");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Ошибка: {ex.Message}");
}
finally
{
_listener?.Stop();
}
}
static async Task HandleClient(TcpClient client, CancellationToken cancellationToken)
{
var clientEndPoint = client.Client.RemoteEndPoint;
Console.WriteLine($"Подключен клиент: {clientEndPoint}");
try
{
using (client)
using (var stream = client.GetStream())
{
var buffer = new byte[1024];
while (!cancellationToken.IsCancellationRequested)
{
try
{
// Чтение данных от клиента с таймаутом
var readTask = stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
var completedTask = await Task.WhenAny(readTask, Task.Delay(1000, cancellationToken));
if (completedTask != readTask)
{
// Таймаут - проверяем отмену и продолжаем цикл
continue;
}
var bytesRead = await readTask;
if (bytesRead == 0)
{
Console.WriteLine($"Клиент отключился: {clientEndPoint}");
break;
}
// Преобразование байтов в строку
var receivedString = Encoding.UTF8.GetString(buffer, 0, bytesRead);
// Удаление символов новой строки для чистого вывода
var cleanString = receivedString.TrimEnd('\n', '\r');
Console.WriteLine($"Получено от {clientEndPoint}: {cleanString}");
// Реверсирование строки
var reversedString = ReverseString(cleanString);
Console.WriteLine($"Отправка: {reversedString}");
// Отправка реверсированной строки обратно клиенту
var responseBytes = Encoding.UTF8.GetBytes(reversedString + Environment.NewLine);
await stream.WriteAsync(responseBytes, 0, responseBytes.Length, cancellationToken);
}
catch (OperationCanceledException)
{
// Игнорируем отмену при чтении/записи
break;
}
}
}
}
catch (Exception ex) when (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine($"Ошибка при работе с клиентом {clientEndPoint}: {ex.Message}");
}
}
static string ReverseString(string s)
{
var charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
}