using System; using System.CommandLine; using System.CommandLine.Parsing; using System.IO; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace f_cln { class Program { static async Task Main(string[] args) { // Создание команды с аргументами Option ipOption = new("address", new[] { "--ip", "-i" }) { Description = "IP адрес сервера (по умолчанию: localhost)", DefaultValueFactory = parseResult => "localhost" }; Option portOption = new("port", new[] { "--port", "-p" }) { Description = "Порт сервера (по умолчанию: 1771)", DefaultValueFactory = parseResult => 1771 }; Option messageOption = new("message", new[] { "--message", "-m" }) { Description = "Сообщение для отправки (если не указано, работает в интерактивном режиме)", Arity = ArgumentArity.ZeroOrOne }; var rootCommand = new RootCommand("Клиент для отправки строк серверу и получения их в обратном порядке") { ipOption, portOption, messageOption }; ParseResult parseResult = rootCommand.Parse(args); if (parseResult.Errors.Count == 0) { string ip = parseResult.GetValue(ipOption) ?? "localhost"; int port = parseResult.GetValue(portOption); string? message = parseResult.GetValue(messageOption); try { if (!string.IsNullOrEmpty(message)) { // Режим однократной отправки return await SendMessage(ip, port, message); } else { // Интерактивный режим return await RunInteractive(ip, port); } } catch (Exception ex) { Console.Error.WriteLine($"Ошибка: {ex.Message}"); return 2; } } else { foreach (ParseError parseError in parseResult.Errors) { Console.Error.WriteLine(parseError.Message); } return 1; } } static async Task SendMessage(string ip, int port, string message) { Console.WriteLine($"Подключение к {ip}:{port}..."); using var client = new TcpClient(); await client.ConnectAsync(ip, port); Console.WriteLine("Подключено к серверу"); using var stream = client.GetStream(); using var reader = new StreamReader(stream, Encoding.UTF8); using var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true }; // Читаем приветственное сообщение var welcomeMessage = await reader.ReadLineAsync(); if (welcomeMessage != null && welcomeMessage.StartsWith("hello ")) { var clientAddress = welcomeMessage[6..]; Console.WriteLine($"Ваш адрес: {clientAddress}"); } // Очистка сообщения string cleanedMessage = CleanInput(message); Console.WriteLine(); // Отправка сообщения await writer.WriteLineAsync(cleanedMessage); Console.WriteLine($"Отправлено: {cleanedMessage}"); // Чтение ответа var response = await reader.ReadLineAsync(); if (response != null) { string cleanedResponse = CleanInput(response); Console.WriteLine($"Ответ: {cleanedResponse}"); return 0; } else { Console.WriteLine("Сервер не ответил"); return 2; } } static async Task RunInteractive(string ip, int port) { Console.WriteLine($"Подключение к {ip}:{port}..."); using var client = new TcpClient(); await client.ConnectAsync(ip, port); Console.WriteLine("Подключено к серверу"); using var stream = client.GetStream(); using var reader = new StreamReader(stream, Encoding.UTF8); using var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true }; // Читаем приветственное сообщение var welcomeMessage = await reader.ReadLineAsync(); if (welcomeMessage != null && welcomeMessage.StartsWith("hello ")) { var clientAddress = welcomeMessage[6..]; Console.WriteLine($"Ваш адрес: {clientAddress}"); } Console.WriteLine(); // Пустая строка для единообразия PrintHelp(); while (true) { try { Console.Write("> "); var input = Console.ReadLine(); if (string.IsNullOrWhiteSpace(input)) continue; // Очистка ввода от непечатаемых символов и BOM input = CleanInput(input); if (string.IsNullOrEmpty(input)) continue; if (input.Equals("exit", StringComparison.OrdinalIgnoreCase) || input.Equals("quit", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("Завершение работы..."); break; } if (input.Equals("help", StringComparison.OrdinalIgnoreCase)) { PrintHelp(); continue; } // Отправка сообщения await writer.WriteLineAsync(input); Console.WriteLine($"Отправлено: {input}"); // Чтение ответа var response = await reader.ReadLineAsync(); if (response != null) { // Очистка ответа от непечатаемых символов response = CleanInput(response); Console.WriteLine($"Ответ: {response}"); } else { Console.WriteLine("Сервер отключился"); return 2; } } catch (Exception ex) when (ex is IOException || ex is ObjectDisposedException) { Console.WriteLine("Соединение с сервером разорвано"); return 2; } catch (Exception ex) { Console.WriteLine($"Ошибка: {ex.Message}"); return 2; } } return 0; } // Метод для очистки строки от непечатаемых символов static string CleanInput(string input) { if (string.IsNullOrEmpty(input)) return input; // Удаляем BOM (U+FEFF) и другие непечатаемые символы var result = new StringBuilder(); foreach (char c in input) { // Оставляем только печатаемые символы и пробелы if (!char.IsControl(c) || c == '\n' || c == '\r' || c == '\t') { result.Append(c); } } return result.ToString().Trim(); } static void PrintHelp() { Console.WriteLine("\n=== Команды клиента ==="); Console.WriteLine(" Просто введите текст для отправки на сервер"); Console.WriteLine(" exit или quit - завершить работу"); Console.WriteLine(" help - показать эту справку"); Console.WriteLine("========================\n"); } } }