Compare commits
4 Commits
74c0b56c41
...
c4fbea36fd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4fbea36fd | ||
|
|
824e816440 | ||
|
|
634ad7e14f | ||
|
|
9b79d41f97 |
118
f-cln/Program.cs
118
f-cln/Program.cs
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.CommandLine;
|
using System.CommandLine;
|
||||||
using System.CommandLine.Parsing;
|
using System.CommandLine.Parsing;
|
||||||
|
using System.IO;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -49,15 +50,13 @@ namespace f_cln
|
|||||||
if (!string.IsNullOrEmpty(message))
|
if (!string.IsNullOrEmpty(message))
|
||||||
{
|
{
|
||||||
// Режим однократной отправки
|
// Режим однократной отправки
|
||||||
await SendMessage(ip, port, message);
|
return await SendMessage(ip, port, message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Интерактивный режим
|
// Интерактивный режим
|
||||||
await RunInteractive(ip, port);
|
return await RunInteractive(ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -75,9 +74,7 @@ namespace f_cln
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task SendMessage(string ip, int port, string message)
|
static async Task<int> SendMessage(string ip, int port, string message)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Подключение к {ip}:{port}...");
|
Console.WriteLine($"Подключение к {ip}:{port}...");
|
||||||
|
|
||||||
@@ -90,32 +87,39 @@ namespace f_cln
|
|||||||
using var reader = new StreamReader(stream, Encoding.UTF8);
|
using var reader = new StreamReader(stream, Encoding.UTF8);
|
||||||
using var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true };
|
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(message);
|
await writer.WriteLineAsync(cleanedMessage);
|
||||||
Console.WriteLine($"Отправлено: {message}");
|
Console.WriteLine($"Отправлено: {cleanedMessage}");
|
||||||
|
|
||||||
// Чтение ответа
|
// Чтение ответа
|
||||||
var response = await reader.ReadLineAsync();
|
var response = await reader.ReadLineAsync();
|
||||||
|
|
||||||
if (response != null)
|
if (response != null)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Получено: {response}");
|
string cleanedResponse = CleanInput(response);
|
||||||
|
Console.WriteLine($"Ответ: {cleanedResponse}");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Сервер не ответил");
|
Console.WriteLine("Сервер не ответил");
|
||||||
}
|
return 2;
|
||||||
}
|
|
||||||
catch (SocketException ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Сетевая ошибка: {ex.Message}");
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task RunInteractive(string ip, int port)
|
static async Task<int> RunInteractive(string ip, int port)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Подключение к {ip}:{port}...");
|
Console.WriteLine($"Подключение к {ip}:{port}...");
|
||||||
|
|
||||||
@@ -123,56 +127,112 @@ namespace f_cln
|
|||||||
await client.ConnectAsync(ip, port);
|
await client.ConnectAsync(ip, port);
|
||||||
|
|
||||||
Console.WriteLine("Подключено к серверу");
|
Console.WriteLine("Подключено к серверу");
|
||||||
Console.WriteLine("Введите текст для отправки (или 'exit' для выхода):");
|
|
||||||
|
|
||||||
using var stream = client.GetStream();
|
using var stream = client.GetStream();
|
||||||
using var reader = new StreamReader(stream, Encoding.UTF8);
|
using var reader = new StreamReader(stream, Encoding.UTF8);
|
||||||
using var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true };
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
// Чтение ввода пользователя
|
try
|
||||||
|
{
|
||||||
Console.Write("> ");
|
Console.Write("> ");
|
||||||
var input = Console.ReadLine();
|
var input = Console.ReadLine();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input))
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (input.Equals("exit", StringComparison.OrdinalIgnoreCase))
|
// Очистка ввода от непечатаемых символов и BOM
|
||||||
|
input = CleanInput(input);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (input.Equals("exit", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
input.Equals("quit", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Завершение работы...");
|
Console.WriteLine("Завершение работы...");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
if (input.Equals("help", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
PrintHelp();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Отправка сообщения
|
// Отправка сообщения
|
||||||
await writer.WriteLineAsync(input);
|
await writer.WriteLineAsync(input);
|
||||||
|
Console.WriteLine($"Отправлено: {input}");
|
||||||
|
|
||||||
// Чтение ответа
|
// Чтение ответа
|
||||||
var response = await reader.ReadLineAsync();
|
var response = await reader.ReadLineAsync();
|
||||||
|
|
||||||
if (response != null)
|
if (response != null)
|
||||||
{
|
{
|
||||||
|
// Очистка ответа от непечатаемых символов
|
||||||
|
response = CleanInput(response);
|
||||||
Console.WriteLine($"Ответ: {response}");
|
Console.WriteLine($"Ответ: {response}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Сервер отключился");
|
Console.WriteLine("Сервер отключился");
|
||||||
break;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) when (ex is IOException || ex is ObjectDisposedException)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Соединение с сервером разорвано");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Ошибка при отправке/получении: {ex.Message}");
|
Console.WriteLine($"Ошибка: {ex.Message}");
|
||||||
break;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
catch (SocketException ex)
|
|
||||||
|
// Метод для очистки строки от непечатаемых символов
|
||||||
|
static string CleanInput(string input)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Ошибка подключения: {ex.Message}");
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"f-cln": {
|
"f-cln": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "-p 1771"
|
"commandLineArgs": "--port 1771 -i fe80::215:5dff:fe12:ec9 -m 123."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
372
f-srv/Program.cs
372
f-srv/Program.cs
@@ -6,6 +6,8 @@ using System.Net.Sockets;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace f_srv
|
namespace f_srv
|
||||||
{
|
{
|
||||||
@@ -13,6 +15,10 @@ namespace f_srv
|
|||||||
{
|
{
|
||||||
private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
|
private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
|
||||||
private static TcpListener? _listener;
|
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)
|
static async Task<int> Main(string[] args)
|
||||||
{
|
{
|
||||||
@@ -20,44 +26,13 @@ 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 =>
|
|
||||||
{
|
|
||||||
if (result.Tokens.Count != 1)
|
|
||||||
{
|
|
||||||
result.AddError("--address requires one argument");
|
|
||||||
return IPAddress.Any;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IPAddress.Parse(result.Tokens.Single().Value);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Option<int> portOption = new("port", new[] { "--port", "-p" })
|
Option<int> portOption = new("port", new[] { "--port", "-p" })
|
||||||
{
|
{
|
||||||
Description = "Порт для прослушивания (по умолчанию: 1771)",
|
Description = "Порт для прослушивания (по умолчанию: 1771)",
|
||||||
DefaultValueFactory = parseResult => 1771,
|
DefaultValueFactory = parseResult => 1771
|
||||||
CustomParser = result =>
|
|
||||||
{
|
|
||||||
if (!result.Tokens.Any())
|
|
||||||
{
|
|
||||||
return 1771;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (int.TryParse(result.Tokens.Single().Value, out var delay))
|
|
||||||
{
|
|
||||||
if (delay < 1)
|
|
||||||
{
|
|
||||||
result.AddError("Must be greater than 0");
|
|
||||||
}
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.AddError("Not an int.");
|
|
||||||
return 0; // Ignored.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var rootCommand = new RootCommand("Сервер для получения строк и отправки их в обратном порядке")
|
var rootCommand = new RootCommand("Сервер для получения строк и отправки их в обратном порядке")
|
||||||
@@ -78,62 +53,130 @@ namespace f_srv
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запускаем сервер в отдельной задаче
|
// Запускаем сервер
|
||||||
var serverTask = Task.Run(() => StartServer(ip, port, _cancellationTokenSource.Token));
|
Console.WriteLine($"Запуск сервера на {ip}:{port}");
|
||||||
|
Console.WriteLine("Команды управления сервером:");
|
||||||
|
Console.WriteLine(" старт - запустить сервер");
|
||||||
|
Console.WriteLine(" стоп - остановить сервер");
|
||||||
|
Console.WriteLine(" пауза - приостановить обработку подключений");
|
||||||
|
Console.WriteLine(" продолжить - возобновить обработку подключений");
|
||||||
|
Console.WriteLine(" рестарт - перезапустить сервер");
|
||||||
|
Console.WriteLine(" статус - показать текущее состояние сервера");
|
||||||
|
Console.WriteLine(" выход - завершить программу");
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
Console.WriteLine("Сервер запущен. Введите 'Exit' для остановки...");
|
// Команда старт по умолчанию
|
||||||
|
await StartServer(ip, port);
|
||||||
|
_isRunning = true;
|
||||||
|
|
||||||
// Ждем ввод строки "Exit" в отдельном потоке
|
// Основной цикл обработки команд
|
||||||
var exitTask = Task.Run(() =>
|
while (true)
|
||||||
{
|
{
|
||||||
while (!_cancellationTokenSource.IsCancellationRequested)
|
Console.Write("сервер> ");
|
||||||
{
|
var command = Console.ReadLine()?.Trim().ToLower();
|
||||||
var input = Console.ReadLine();
|
|
||||||
if (!string.IsNullOrEmpty(input) &&
|
|
||||||
input.Trim().Equals("Exit", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ожидаем либо ввод "Exit", либо завершение сервера
|
if (string.IsNullOrEmpty(command))
|
||||||
var completedTask = await Task.WhenAny(serverTask, exitTask);
|
continue;
|
||||||
|
|
||||||
if (completedTask == exitTask && exitTask.Result)
|
switch (command)
|
||||||
{
|
{
|
||||||
// Пользователь ввел Exit
|
case "старт":
|
||||||
if (!_cancellationTokenSource.IsCancellationRequested)
|
if (!_isRunning)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Остановка сервера...");
|
await StartServer(ip, port);
|
||||||
_cancellationTokenSource.Cancel();
|
_isRunning = true;
|
||||||
_listener?.Stop();
|
Console.WriteLine("Сервер запущен");
|
||||||
|
|
||||||
// Даем серверу время на корректное завершение
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.WhenAny(serverTask, Task.Delay(2000));
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Игнорируем исключения при завершении
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Сервер остановлен.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Сервер завершился сам (ошибка или другая причина)
|
Console.WriteLine("Сервер уже запущен");
|
||||||
if (!_cancellationTokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
_cancellationTokenSource.Cancel();
|
|
||||||
}
|
}
|
||||||
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;
|
return 0;
|
||||||
|
|
||||||
|
case "помощь":
|
||||||
|
case "help":
|
||||||
|
PrintHelp();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"Неизвестная команда: {command}");
|
||||||
|
Console.WriteLine("Введите 'помощь' для списка команд");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -145,38 +188,56 @@ namespace f_srv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task StartServer(IPAddress ip, int port, CancellationToken cancellationToken)
|
static async Task StartServer(IPAddress ip, int port)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Запуск сервера на {ip}:{port}");
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
_isPaused = false;
|
||||||
|
_connectedClients.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Создание TCP listener
|
// Создание TCP listener
|
||||||
_listener = new TcpListener(ip, port);
|
_listener = new TcpListener(ip, port);
|
||||||
_listener.Start();
|
_listener.Start();
|
||||||
|
|
||||||
Console.WriteLine("Сервер запущен. Ожидание подключений...");
|
Console.WriteLine($"Сервер запущен на {ip}:{port}");
|
||||||
|
Console.WriteLine("Ожидание подключений...");
|
||||||
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
// Запускаем обработку подключений в фоновом потоке
|
||||||
|
_ = Task.Run(() => AcceptConnectionsAsync());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Ошибка при запуске сервера: {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task AcceptConnectionsAsync()
|
||||||
|
{
|
||||||
|
while (!_cancellationTokenSource.Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Ожидание подключения клиента с таймаутом для проверки отмены
|
// Если сервер на паузе, ждем
|
||||||
var acceptTask = _listener.AcceptTcpClientAsync();
|
if (_isPaused)
|
||||||
var completedTask = await Task.WhenAny(acceptTask, Task.Delay(1000, cancellationToken));
|
|
||||||
|
|
||||||
if (completedTask == acceptTask && !cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
{
|
||||||
var client = await acceptTask;
|
await Task.Delay(1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ожидание подключения клиента
|
||||||
|
var client = await _listener!.AcceptTcpClientAsync();
|
||||||
|
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
_connectedClients.Add(client);
|
||||||
|
}
|
||||||
|
|
||||||
// Обработка клиента в отдельной задаче
|
// Обработка клиента в отдельной задаче
|
||||||
_ = Task.Run(async () => await HandleClient(client, cancellationToken));
|
_ = Task.Run(async () => await HandleClient(client));
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
// Игнорируем отмену
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
@@ -185,34 +246,15 @@ namespace f_srv
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (!cancellationToken.IsCancellationRequested)
|
if (!_cancellationTokenSource.Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Ошибка при принятии подключения: {ex.Message}");
|
Console.WriteLine($"Ошибка при принятии подключения: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Ошибка: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_listener?.Stop();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Игнорируем ошибки при остановке
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async Task HandleClient(TcpClient client, CancellationToken cancellationToken)
|
static async Task HandleClient(TcpClient client)
|
||||||
{
|
{
|
||||||
var clientEndPoint = client.Client.RemoteEndPoint;
|
var clientEndPoint = client.Client.RemoteEndPoint;
|
||||||
Console.WriteLine($"Подключен клиент: {clientEndPoint}");
|
Console.WriteLine($"Подключен клиент: {clientEndPoint}");
|
||||||
@@ -224,7 +266,10 @@ namespace f_srv
|
|||||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
||||||
using (var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true })
|
using (var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true })
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
// Отправка приветственного сообщения
|
||||||
|
await writer.WriteLineAsync($"hello {clientEndPoint}");
|
||||||
|
|
||||||
|
while (client.Connected && !_cancellationTokenSource.Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -238,6 +283,13 @@ namespace f_srv
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Если сервер на паузе, ждем
|
||||||
|
if (_isPaused)
|
||||||
|
{
|
||||||
|
await writer.WriteLineAsync("Сервер приостановлен. Попробуйте позже.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Получено от {clientEndPoint}: {line}");
|
Console.WriteLine($"Получено от {clientEndPoint}: {line}");
|
||||||
|
|
||||||
// Реверсирование строки
|
// Реверсирование строки
|
||||||
@@ -247,11 +299,6 @@ namespace f_srv
|
|||||||
// Отправка реверсированной строки обратно клиенту
|
// Отправка реверсированной строки обратно клиенту
|
||||||
await writer.WriteLineAsync(reversedString);
|
await writer.WriteLineAsync(reversedString);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
// Игнорируем отмену при чтении/записи
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
// Ошибка ввода/вывода - клиент отключился
|
// Ошибка ввода/вывода - клиент отключился
|
||||||
@@ -261,10 +308,95 @@ namespace f_srv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) when (!cancellationToken.IsCancellationRequested)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Ошибка при работе с клиентом {clientEndPoint}: {ex.Message}");
|
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)
|
static string ReverseString(string s)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"f-srv": {
|
"f-srv": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "--port 3113 -i 192.168.15.128"
|
"commandLineArgs": "--port 1771 -i 127.0.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user