create server & client

This commit is contained in:
Sharikov P.P.
2026-01-16 00:30:19 +07:00
parent 879485cb54
commit cc41ec4f55
8 changed files with 884 additions and 0 deletions

206
f-srv/Program.cs Normal file
View File

@@ -0,0 +1,206 @@
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);
}
}
}