-
Notifications
You must be signed in to change notification settings - Fork 0
thirdTest #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
thirdTest #8
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 17 | ||
| VisualStudioVersion = 17.13.35806.99 d17.13 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "thirdTestTask", "thirdTestTask\thirdTestTask.csproj", "{0B8D0C96-1815-4C28-962A-89EEA36DAC6C}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {0B8D0C96-1815-4C28-962A-89EEA36DAC6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {0B8D0C96-1815-4C28-962A-89EEA36DAC6C}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {0B8D0C96-1815-4C28-962A-89EEA36DAC6C}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {0B8D0C96-1815-4C28-962A-89EEA36DAC6C}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ExtensibilityGlobals) = postSolution | ||
| SolutionGuid = {B5862231-4F8A-4732-BBF1-C911C3298007} | ||
| EndGlobalSection | ||
| EndGlobal |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Net; | ||
| using System.Text; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace thirdTestTask; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Пространства имён в .NET именуются с заглавной всегда |
||
|
|
||
| public static class App | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Комментариев не хватает |
||
| { | ||
| public static async Task<int> Run(string[] args) | ||
| { | ||
| if (TryParseServer(args, out int serverPort)) | ||
| { | ||
| await ServerHost.RunOnce(serverPort); | ||
| return 0; | ||
| } | ||
|
|
||
| if (TryParseClient(args, out IPAddress? ip, out int clientPort)) | ||
| { | ||
| await ClientHost.Run(ip!, clientPort); | ||
| return 0; | ||
| } | ||
|
|
||
| PrintUsage(); | ||
| return 2; | ||
| } | ||
|
|
||
| private static bool TryParseServer(string[] args, out int port) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. out-переменные — большая редкость в современном C#, где есть кортежи. Это нейросеть так пишет? :) |
||
| { | ||
| port = 0; | ||
| return args.Length == 1 && int.TryParse(args[0], out port); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Стоило бы заодно проверить, принадлежит ли номер порта разрешённому диапазону. |
||
| } | ||
|
|
||
| private static bool TryParseClient(string[] args, out IPAddress? ip, out int port) | ||
| { | ||
| ip = null; | ||
| port = 0; | ||
|
|
||
| return args.Length == 2 && IPAddress.TryParse(args[0], out ip) && int.TryParse(args[1], out port); | ||
| } | ||
|
|
||
| private static void PrintUsage() | ||
| { | ||
| Console.WriteLine("Использование:"); | ||
| Console.WriteLine("Сервер: <port>"); | ||
| Console.WriteLine("Клиент: <ip> <port>"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Net.Sockets; | ||
| using System.Text; | ||
| using System.Text.Unicode; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace thirdTestTask; | ||
|
|
||
| public static class ChatSession | ||
| { | ||
| public static async Task RunAsync(TcpClient client, TextReader input, TextWriter output, CancellationToken token = default) | ||
| { | ||
| using var cts = CancellationTokenSource.CreateLinkedTokenSource(token); | ||
| CancellationToken token2 = cts.Token; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Что-то сложно. Можно было дальше cts.Token и использовать |
||
|
|
||
| NetworkStream stream = client.GetStream(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using? Клиент сам его закроет, но вообще NetworkStream IDisposable, поэтому можно дать ему самому разобраться, когда надо закрыться |
||
|
|
||
| using var reader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true); | ||
| using var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 1024, leaveOpen: true){ AutoFlush = true }; | ||
| Task receiveTask = Task.Run(async () => | ||
| { | ||
| try | ||
| { | ||
| while (!token2.IsCancellationRequested) | ||
| { | ||
| string? msg = await reader.ReadLineAsync(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Сюда бы тоже CancellationToken, чтобы мы не ждали вечно сообщения |
||
|
|
||
| if (msg == null) | ||
| { | ||
| await SafeWriteLineAsync(output, "\n[СИСТЕМА] Соединение разорвано."); | ||
| cts.Cancel(); | ||
| break; | ||
| } | ||
|
|
||
| if (IsExit(msg)) | ||
| { | ||
| await SafeWriteLineAsync(output, "\n[СИСТЕМА] Собеседник завершил чат."); | ||
| cts.Cancel(); | ||
| break; | ||
| } | ||
|
|
||
| await SafeWriteLineAsync(output, $"[Собеседник]: {msg}"); | ||
| } | ||
| } | ||
| catch | ||
| { | ||
| cts.Cancel(); | ||
| } | ||
| }, token2); | ||
|
|
||
| Task sendTask = Task.Run(async () => | ||
| { | ||
| try | ||
| { | ||
| while (!token2.IsCancellationRequested) | ||
| { | ||
| string? line = await ReadLineWithCancelAsync(input, token2); | ||
|
|
||
| if (line == null) | ||
| { | ||
| cts.Cancel(); | ||
| break; | ||
| } | ||
|
|
||
| if (string.IsNullOrWhiteSpace(line)) | ||
| continue; | ||
|
|
||
| await writer.WriteLineAsync(line); | ||
|
|
||
| if (IsExit(line)) | ||
| { | ||
| cts.Cancel(); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| catch | ||
| { | ||
| cts.Cancel(); | ||
| } | ||
| }, token2); | ||
|
|
||
| await Task.WhenAny(receiveTask, sendTask); | ||
|
|
||
| try { client.Close(); } | ||
| catch { } | ||
|
|
||
| cts.Cancel(); | ||
| try { await Task.WhenAll(receiveTask, sendTask); } | ||
| catch { } | ||
| } | ||
|
|
||
| private static bool IsExit(string s) | ||
| => s.Trim().Equals("exit", StringComparison.OrdinalIgnoreCase); | ||
|
|
||
| private static Task SafeWriteLineAsync(TextWriter output, string text) | ||
| { | ||
| output.WriteLine(text); | ||
| output.Flush(); | ||
| return Task.CompletedTask; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ну такое это async. Выглядит как обман почтенной публики, операция выполняется синхронно |
||
| } | ||
|
|
||
| private static async Task<string?> ReadLineWithCancelAsync(TextReader input, CancellationToken token) | ||
| { | ||
| Task<string?> readTask = input.ReadLineAsync(); | ||
| Task done = await Task.WhenAny(readTask, Task.Delay(Timeout.Infinite, token)); | ||
|
|
||
| if (done != readTask) return null; | ||
| return await readTask; | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Net; | ||
| using System.Net.Sockets; | ||
| using System.Text; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace thirdTestTask; | ||
|
|
||
| public static class ClientHost | ||
| { | ||
| public static async Task Run(IPAddress ip, int port) | ||
| { | ||
| using var client = new TcpClient(); | ||
|
|
||
| Console.WriteLine($"[Клиент] подключение к {ip}: {port} "); | ||
| await client.ConnectAsync(ip, port); | ||
|
|
||
| Console.WriteLine("[Клиент] подключено. Для выхода - exit"); | ||
| await ChatSession.RunAsync(client, Console.In, Console.Out); | ||
|
|
||
| Console.WriteLine("[Клиент] завершение"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| using thirdTestTask; | ||
|
|
||
| await App.Run(args); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||
| using System; | ||||||
| using System.Collections.Generic; | ||||||
| using System.Linq; | ||||||
| using System.Net; | ||||||
| using System.Net.Sockets; | ||||||
| using System.Text; | ||||||
| using System.Threading.Tasks; | ||||||
|
|
||||||
| namespace thirdTestTask; | ||||||
|
|
||||||
| public static class ServerHost | ||||||
| { | ||||||
| public static async Task RunOnce(int port) | ||||||
| { | ||||||
| var listner = new TcpListener(IPAddress.Any, port); | ||||||
| listner.Start(); | ||||||
|
|
||||||
| try | ||||||
| { | ||||||
| Console.WriteLine($"[Сервер] Ожидание подлюкчения на порту {port}..."); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| using TcpClient client = await listner.AcceptTcpClientAsync(); | ||||||
|
|
||||||
| Console.WriteLine("[Сервер] Клиент подключился. Для выхода - exit"); | ||||||
| await ChatSession.RunAsync(client, Console.In, Console.Out); | ||||||
| } | ||||||
|
|
||||||
| finally | ||||||
| { | ||||||
| listner.Stop(); | ||||||
| Console.WriteLine("[Сервер] Завершение"); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. StyleCop бы ещё |
||
|
|
||
| </Project> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Подозреваю, что тут много ненужных using-ов, и их лучше внутри namespace писать