409 lines
17 KiB
C#
409 lines
17 KiB
C#
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;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
|
||
namespace f_srv
|
||
{
|
||
class Program
|
||
{
|
||
private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
|
||
private static TcpListener? _listener;
|
||
private static bool _isPaused = false;
|
||
private static readonly object _lockObject = new object();
|
||
private static List<TcpClient> _connectedClients = new List<TcpClient>();
|
||
private static bool _isRunning = false;
|
||
|
||
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
|
||
};
|
||
|
||
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;
|
||
}
|
||
|
||
// Запускаем сервер
|
||
Console.WriteLine($"Запуск сервера на {ip}:{port}");
|
||
Console.WriteLine("Команды управления сервером:");
|
||
Console.WriteLine(" старт - запустить сервер");
|
||
Console.WriteLine(" стоп - остановить сервер");
|
||
Console.WriteLine(" пауза - приостановить обработку подключений");
|
||
Console.WriteLine(" продолжить - возобновить обработку подключений");
|
||
Console.WriteLine(" рестарт - перезапустить сервер");
|
||
Console.WriteLine(" статус - показать текущее состояние сервера");
|
||
Console.WriteLine(" выход - завершить программу");
|
||
Console.WriteLine();
|
||
|
||
// Команда старт по умолчанию
|
||
await StartServer(ip, port);
|
||
_isRunning = true;
|
||
|
||
// Основной цикл обработки команд
|
||
while (true)
|
||
{
|
||
Console.Write("сервер> ");
|
||
var command = Console.ReadLine()?.Trim().ToLower();
|
||
|
||
if (string.IsNullOrEmpty(command))
|
||
continue;
|
||
|
||
switch (command)
|
||
{
|
||
case "старт":
|
||
if (!_isRunning)
|
||
{
|
||
await StartServer(ip, port);
|
||
_isRunning = true;
|
||
Console.WriteLine("Сервер запущен");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("Сервер уже запущен");
|
||
}
|
||
break;
|
||
|
||
case "стоп":
|
||
if (_isRunning)
|
||
{
|
||
await StopServer();
|
||
_isRunning = false;
|
||
Console.WriteLine("Сервер остановлен");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("Сервер уже остановлен");
|
||
}
|
||
break;
|
||
|
||
case "пауза":
|
||
if (_isRunning && !_isPaused)
|
||
{
|
||
_isPaused = true;
|
||
Console.WriteLine("Сервер приостановлен. Новые подключения не обрабатываются.");
|
||
}
|
||
else if (!_isRunning)
|
||
{
|
||
Console.WriteLine("Сервер не запущен");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("Сервер уже приостановлен");
|
||
}
|
||
break;
|
||
|
||
case "продолжить":
|
||
if (_isRunning && _isPaused)
|
||
{
|
||
_isPaused = false;
|
||
Console.WriteLine("Сервер возобновил работу");
|
||
}
|
||
else if (!_isRunning)
|
||
{
|
||
Console.WriteLine("Сервер не запущен");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("Сервер уже работает");
|
||
}
|
||
break;
|
||
|
||
case "рестарт":
|
||
if (_isRunning)
|
||
{
|
||
await StopServer();
|
||
Console.WriteLine("Сервер остановлен");
|
||
}
|
||
|
||
await Task.Delay(1000); // Небольшая задержка перед перезапуском
|
||
await StartServer(ip, port);
|
||
_isRunning = true;
|
||
_isPaused = false;
|
||
Console.WriteLine("Сервер перезапущен");
|
||
break;
|
||
|
||
case "статус":
|
||
PrintServerStatus();
|
||
break;
|
||
|
||
case "выход":
|
||
case "exit":
|
||
Console.WriteLine("Завершение работы сервера...");
|
||
if (_isRunning)
|
||
{
|
||
await StopServer();
|
||
}
|
||
_cancellationTokenSource.Cancel();
|
||
return 0;
|
||
|
||
case "помощь":
|
||
case "help":
|
||
PrintHelp();
|
||
break;
|
||
|
||
default:
|
||
Console.WriteLine($"Неизвестная команда: {command}");
|
||
Console.WriteLine("Введите 'помощь' для списка команд");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
foreach (ParseError parseError in parseResult.Errors)
|
||
{
|
||
Console.Error.WriteLine(parseError.Message);
|
||
}
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
static async Task StartServer(IPAddress ip, int port)
|
||
{
|
||
try
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
_isPaused = false;
|
||
_connectedClients.Clear();
|
||
}
|
||
|
||
// Создание TCP listener
|
||
_listener = new TcpListener(ip, port);
|
||
_listener.Start();
|
||
|
||
Console.WriteLine($"Сервер запущен на {ip}:{port}");
|
||
Console.WriteLine("Ожидание подключений...");
|
||
|
||
// Запускаем обработку подключений в фоновом потоке
|
||
_ = Task.Run(() => AcceptConnectionsAsync());
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Ошибка при запуске сервера: {ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
static async Task AcceptConnectionsAsync()
|
||
{
|
||
while (!_cancellationTokenSource.Token.IsCancellationRequested)
|
||
{
|
||
try
|
||
{
|
||
// Если сервер на паузе, ждем
|
||
if (_isPaused)
|
||
{
|
||
await Task.Delay(1000);
|
||
continue;
|
||
}
|
||
|
||
// Ожидание подключения клиента
|
||
var client = await _listener!.AcceptTcpClientAsync();
|
||
|
||
lock (_lockObject)
|
||
{
|
||
_connectedClients.Add(client);
|
||
}
|
||
|
||
// Обработка клиента в отдельной задаче
|
||
_ = Task.Run(async () => await HandleClient(client));
|
||
}
|
||
catch (ObjectDisposedException)
|
||
{
|
||
// Listener был остановлен
|
||
break;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (!_cancellationTokenSource.Token.IsCancellationRequested)
|
||
{
|
||
Console.WriteLine($"Ошибка при принятии подключения: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static async Task HandleClient(TcpClient client)
|
||
{
|
||
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 })
|
||
{
|
||
// Отправка приветственного сообщения
|
||
await writer.WriteLineAsync($"hello {clientEndPoint}");
|
||
|
||
while (client.Connected && !_cancellationTokenSource.Token.IsCancellationRequested)
|
||
{
|
||
try
|
||
{
|
||
// Чтение строки (до символа новой строки)
|
||
var line = await reader.ReadLineAsync();
|
||
|
||
if (line == null)
|
||
{
|
||
// Клиент отключился
|
||
Console.WriteLine($"Клиент отключился: {clientEndPoint}");
|
||
break;
|
||
}
|
||
|
||
// Если сервер на паузе, ждем
|
||
if (_isPaused)
|
||
{
|
||
await writer.WriteLineAsync("Сервер приостановлен. Попробуйте позже.");
|
||
continue;
|
||
}
|
||
|
||
Console.WriteLine($"Получено от {clientEndPoint}: {line}");
|
||
|
||
// Реверсирование строки
|
||
var reversedString = ReverseString(line);
|
||
Console.WriteLine($"Отправка: {reversedString}");
|
||
|
||
// Отправка реверсированной строки обратно клиенту
|
||
await writer.WriteLineAsync(reversedString);
|
||
}
|
||
catch (IOException ex)
|
||
{
|
||
// Ошибка ввода/вывода - клиент отключился
|
||
Console.WriteLine($"Клиент отключился: {clientEndPoint} - {ex.Message}");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Ошибка при работе с клиентом {clientEndPoint}: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
_connectedClients.Remove(client);
|
||
}
|
||
Console.WriteLine($"Клиент отключен: {clientEndPoint}");
|
||
}
|
||
}
|
||
|
||
static async Task StopServer()
|
||
{
|
||
try
|
||
{
|
||
// Останавливаем listener
|
||
_listener?.Stop();
|
||
|
||
// Закрываем все подключенные клиенты
|
||
lock (_lockObject)
|
||
{
|
||
foreach (var client in _connectedClients.ToList())
|
||
{
|
||
try
|
||
{
|
||
client.Close();
|
||
}
|
||
catch
|
||
{
|
||
// Игнорируем ошибки при закрытии клиентов
|
||
}
|
||
}
|
||
_connectedClients.Clear();
|
||
}
|
||
|
||
_isPaused = false;
|
||
Console.WriteLine("Сервер остановлен");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Ошибка при остановке сервера: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
static void PrintServerStatus()
|
||
{
|
||
Console.WriteLine("\n=== Статус сервера ===");
|
||
Console.WriteLine($"Состояние: {(_isRunning ? "Запущен" : "Остановлен")}");
|
||
if (_isRunning)
|
||
{
|
||
Console.WriteLine($"Режим: {(_isPaused ? "Приостановлен" : "Работает")}");
|
||
|
||
lock (_lockObject)
|
||
{
|
||
Console.WriteLine($"Подключенных клиентов: {_connectedClients.Count}");
|
||
foreach (var client in _connectedClients)
|
||
{
|
||
try
|
||
{
|
||
if (client.Client.RemoteEndPoint is IPEndPoint endPoint)
|
||
{
|
||
Console.WriteLine($" {endPoint.Address}:{endPoint.Port}");
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// Игнорируем клиентов с ошибками
|
||
}
|
||
}
|
||
}
|
||
}
|
||
Console.WriteLine("====================\n");
|
||
}
|
||
|
||
static void PrintHelp()
|
||
{
|
||
Console.WriteLine("\n=== Команды управления сервером ===");
|
||
Console.WriteLine(" старт - запустить сервер");
|
||
Console.WriteLine(" стоп - остановить сервер");
|
||
Console.WriteLine(" пауза - приостановить обработку подключений");
|
||
Console.WriteLine(" продолжить - возобновить обработку подключений");
|
||
Console.WriteLine(" рестарт - перезапустить сервер");
|
||
Console.WriteLine(" статус - показать текущее состояние сервера");
|
||
Console.WriteLine(" помощь - показать эту справку");
|
||
Console.WriteLine(" выход - завершить программу");
|
||
Console.WriteLine("===================================\n");
|
||
}
|
||
|
||
static string ReverseString(string s)
|
||
{
|
||
var charArray = s.ToCharArray();
|
||
Array.Reverse(charArray);
|
||
return new string(charArray);
|
||
}
|
||
}
|
||
} |