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 Main(string[] args) { // Создание команды с аргументами Option ipOption = new("address", new[] { "--ip", "-i" }) { Description = "IP адрес для прослушивания (по умолчанию: все интерфейсы)", DefaultValueFactory = parseResult => IPAddress.Any }; Option portOption = new("port", new[] { "--port", "-p" }) { Description = "Порт для прослушивания (по умолчанию: 1771)", DefaultValueFactory = parseResult => 1771 }; var rootCommand = new RootCommand("Сервер для получения строк и отправки их в обратном порядке") { ipOption, portOption }; 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("Сервер запущен. Нажмите любую клавишу для остановки..."); ConsoleKeyInfo ki = Console.ReadKey(); // Отправляем сигнал отмены _cancellationTokenSource.Cancel(); // Останавливаем listener _listener?.Stop(); // Ждем завершения сервера await serverTask; if (Console.KeyAvailable) { ConsoleKeyInfo key = Console.ReadKey(); } Console.WriteLine(" \r\n "); 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()) using (var reader = new StreamReader(stream, Encoding.UTF8)) using (var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true }) { var buffer = new StringBuilder(); var charBuffer = new char[1024]; while (!cancellationToken.IsCancellationRequested) { try { // Чтение строки (до символа новой строки) var line = await reader.ReadLineAsync(cancellationToken); if (line == null) { // Клиент отключился Console.WriteLine($"Клиент отключился: {clientEndPoint}"); break; } Console.WriteLine($"Получено от {clientEndPoint}: {line}"); // Реверсирование строки var reversedString = ReverseString(line); Console.WriteLine($"Отправка: {reversedString}"); // Отправка реверсированной строки обратно клиенту await writer.WriteLineAsync(reversedString); } catch (OperationCanceledException) { // Игнорируем отмену при чтении/записи break; } catch (IOException ex) { // Ошибка ввода/вывода - клиент отключился Console.WriteLine($"Клиент отключился: {clientEndPoint} - {ex.Message}"); 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); } } }