-
Notifications
You must be signed in to change notification settings - Fork 0
Server #4
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?
Server #4
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,31 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 17 | ||
| VisualStudioVersion = 17.2.32505.173 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{A00779F1-A313-4AFA-9CA9-FC8751E23609}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerTest", "ServerTest\ServerTest.csproj", "{466C5BB4-D15D-47CE-84BE-6A52D07040CC}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {A00779F1-A313-4AFA-9CA9-FC8751E23609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {A00779F1-A313-4AFA-9CA9-FC8751E23609}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {A00779F1-A313-4AFA-9CA9-FC8751E23609}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {A00779F1-A313-4AFA-9CA9-FC8751E23609}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {466C5BB4-D15D-47CE-84BE-6A52D07040CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {466C5BB4-D15D-47CE-84BE-6A52D07040CC}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {466C5BB4-D15D-47CE-84BE-6A52D07040CC}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {466C5BB4-D15D-47CE-84BE-6A52D07040CC}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ExtensibilityGlobals) = postSolution | ||
| SolutionGuid = {E304F713-BA15-432A-8DB6-6474FD71D207} | ||
| EndGlobalSection | ||
| EndGlobal |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| namespace Server; | ||
|
|
||
| using System.Net.Sockets; | ||
| using System.Net; | ||
|
|
||
| /// <summary> | ||
| /// Сlass representing the client | ||
| /// </summary> | ||
| public class Client | ||
| { | ||
| private readonly int port; | ||
| private readonly IPAddress address; | ||
|
|
||
| /// <summary> | ||
| /// Сonstructor | ||
| /// </summary> | ||
| /// <param name="adress">ip adress</param> | ||
| /// <param name="port">port</param> | ||
| public Client(IPAddress adress, int port) | ||
| { | ||
| this.port = port; | ||
| this.address = adress; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Method for listing files | ||
| /// </summary> | ||
| /// <param name="stream">stream</param> | ||
| /// <param name="path">path to directory</param> | ||
| /// <returns></returns> | ||
| public async Task<(int, List<(string, bool)>)> List(string pathToDiretory) | ||
| { | ||
| var client = new TcpClient(); | ||
|
|
||
| // Подключаемся к узлу | ||
| await client.ConnectAsync(address, port); | ||
|
|
||
| // Получаем поток для записи и чтения | ||
| using var 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 var streamWriter = new StreamWriter(stream) { AutoFlush = true }; | ||
|
|
||
| // Отправляем сообщение подключенному tcpсерверу. | ||
| await streamWriter.WriteLineAsync($"list {pathToDiretory}"); | ||
|
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. Нарушение протокола, list в условии кодируется единицей |
||
| using var streamReader = new StreamReader(stream); | ||
|
|
||
| // Получаем ответ от сервера | ||
| var data = await streamReader.ReadLineAsync(); | ||
| if (data == null) | ||
| { | ||
| throw new InvalidDataException(); | ||
| } | ||
|
|
||
| var strings = data.Split(' '); | ||
| if (!int.TryParse(strings[0], out int size)) | ||
| { | ||
| throw new InvalidDataException(); | ||
| } | ||
|
|
||
| if (size == -1) | ||
| { | ||
| throw new DirectoryNotFoundException(); | ||
| } | ||
|
|
||
| var list = new List<(string, bool)>(); | ||
| for (int i = 1; i < strings.Length; i++) | ||
| { | ||
| bool flag = strings[i + 1] != "false"; | ||
| list.Add((strings[i], flag)); | ||
| i++; | ||
| } | ||
|
|
||
| return (size, list); | ||
|
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. Список сам знает свой размер, так что size несколько избыточен |
||
| } | ||
|
|
||
| /// <summary> | ||
| /// Method for get files | ||
| /// </summary> | ||
| /// <param name="stream">stream</param> | ||
| /// <param name="path">path to file</param> | ||
| /// <returns></returns> | ||
| public async Task<(int, byte[])> Get(string pathToFile) | ||
| { | ||
| var client = new TcpClient(); | ||
| await client.ConnectAsync(address, port); | ||
| using var stream = client.GetStream(); | ||
| using var streamWriter = new StreamWriter(stream) { AutoFlush = true }; | ||
| await streamWriter.WriteLineAsync($"get {pathToFile}"); | ||
| using var streamReader = new StreamReader(stream); | ||
| var stringWithSize = (await streamReader.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. Скобки не нужны |
||
| if (!int.TryParse(stringWithSize, out int size)) | ||
| { | ||
| throw new InvalidDataException(); | ||
| } | ||
|
|
||
| if (size == -1) | ||
| { | ||
| throw new FileNotFoundException(); | ||
| } | ||
|
|
||
| var buffer = new byte[size]; | ||
|
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. Тут лучше CopyToAsync и в память не писать (а принимать стрим в Get). Потому что файлы могут быть большими |
||
| await streamReader.BaseStream.ReadAsync(buffer, 0, size); | ||
| return (size, buffer); | ||
|
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. И тут. Массив тоже знает свой размер |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| namespace Server; | ||
|
|
||
| using System.Net.Sockets; | ||
| using System.Net; | ||
|
|
||
| /// <summary> | ||
| /// Class representing the server | ||
| /// </summary> | ||
| public class Server | ||
| { | ||
| private readonly int port; | ||
| private readonly IPAddress address; | ||
|
|
||
| /// <summary> | ||
| /// Сonstructor | ||
| /// </summary> | ||
| /// <param name="adress">ip adress</param> | ||
| /// <param name="port">port</param> | ||
| public Server(IPAddress adress, int port) | ||
| { | ||
| this.address = adress; | ||
| this.port = port; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Method for listing files | ||
| /// </summary> | ||
| /// <param name="stream">stream</param> | ||
| /// <param name="path">path to directory</param> | ||
| /// <returns></returns> | ||
| private static async Task List(NetworkStream stream, string path) | ||
| { | ||
| using var streamWriter = new StreamWriter(stream) { AutoFlush = true }; | ||
|
|
||
| if (!Directory.Exists(path)) | ||
| { | ||
| await streamWriter.WriteAsync("-1"); | ||
| return; | ||
| } | ||
|
|
||
| var directories = Directory.GetDirectories(path); | ||
| var files = Directory.GetFiles(path); | ||
| var size = directories.Length + files.Length; | ||
|
|
||
| await streamWriter.WriteAsync(size.ToString()); | ||
|
|
||
| foreach (var file in files) | ||
| { | ||
| await streamWriter.WriteAsync($" {file} false"); | ||
| } | ||
|
|
||
| foreach (var directory in directories) | ||
| { | ||
| await streamWriter.WriteAsync($" {directory} true"); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Method for get files | ||
| /// </summary> | ||
| /// <param name="stream">stream</param> | ||
| /// <param name="path">path to file</param> | ||
| /// <returns></returns> | ||
| private static async Task Get(NetworkStream stream, string path) | ||
| { | ||
| using var streamWriter = new StreamWriter(stream) { AutoFlush = true }; | ||
| if (!File.Exists(path)) | ||
| { | ||
| await streamWriter.WriteAsync("-1"); | ||
| return; | ||
| } | ||
|
|
||
| var size = (new FileInfo(path)).Length; | ||
|
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. Тут тоже лишние скобки |
||
| await streamWriter.WriteLineAsync(size.ToString()); | ||
| using var fileStream = new FileStream(path, FileMode.Open); | ||
| await fileStream.CopyToAsync(streamWriter.BaseStream); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Function to start the server (it will start listening for connections from clients) | ||
| /// </summary> | ||
| /// <returns></returns> | ||
| public async Task Start(CancellationTokenSource source) | ||
| { | ||
| var tcpListener = new TcpListener(address, port); | ||
|
|
||
| // Слушаем порт | ||
| tcpListener.Start(); | ||
|
|
||
| while (!source.Token.IsCancellationRequested) | ||
| { | ||
| // Блокируем поток до установления соединения | ||
| var acceptedSocket = await tcpListener.AcceptSocketAsync(); | ||
|
|
||
| // Каждый клиент обслуживается в своем потоке. Т.к. async, то не будет блокировок при чтении больших файлов | ||
| await Task.Run(async() => | ||
|
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. Не, await и Task.Run — это взаимнообратные операции. Так мы всё равно не сможем обслужить второго клиента, пока первый не отключится. Надо создать таск, и пусть он работает, а мы пока будем слушать новые подключения |
||
| { | ||
| // Поток для записи и чтения в полученный сокет | ||
| using var newtworkStream = new NetworkStream(acceptedSocket); | ||
|
|
||
| // Получаем сообщение от клиента | ||
| using var streamReader = new StreamReader(newtworkStream); | ||
| var strings = (streamReader.ReadLine())?.Split(' '); | ||
| if (strings == null) | ||
| { | ||
| throw new InvalidDataException(); | ||
| } | ||
|
|
||
| switch (strings[0]) | ||
| { | ||
| case "list": | ||
| { | ||
| await List(newtworkStream, strings[1]); | ||
| break; | ||
| } | ||
| case "get": | ||
| { | ||
| await Get(newtworkStream, strings[1]); | ||
| break; | ||
| } | ||
| default: | ||
| { | ||
| throw new InvalidDataException(); | ||
| } | ||
| } | ||
|
|
||
| acceptedSocket.Close(); | ||
|
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 (acceptedSocket) { ... }, иначе этот код небезопасен с точки зрения исключений |
||
| }); | ||
| } | ||
|
|
||
| tcpListener.Stop(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net6.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,72 @@ | ||||||
| using System.Net; | ||||||
|
|
||||||
| Console.WriteLine("Формат ввода через командную строку"); | ||||||
| Console.WriteLine("string: IPaddress"); | ||||||
| Console.WriteLine("int: IPaddress"); | ||||||
| Console.WriteLine($"get string :path to file"); | ||||||
| Console.WriteLine($"list string :path to directory"); | ||||||
| Console.WriteLine($"Например: {"127.0.0.1"} {"80"} {"list ./File"} {"get ./File/File.txt"}"); | ||||||
|
|
||||||
| if (args.Length < 3) | ||||||
| { | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| if (!IPAddress.TryParse(args[0], out IPAddress? ip)) | ||||||
| { | ||||||
| Console.WriteLine("incorrect ip address input"); | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| if (!int.TryParse(args[1], out int port)) | ||||||
| { | ||||||
| Console.WriteLine("incorrect port input"); | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| if (port < 1024 || port > 65535) | ||||||
| { | ||||||
| Console.WriteLine("incorrect port input"); | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| var server = new Server.Server(ip!, port); | ||||||
| var cancelTokenSource = new CancellationTokenSource(); | ||||||
|
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. По-хорошему, сервер надо остановить в конце и дождаться остановки |
||||||
| var serverTask = Task.Run(() => server.Start(cancelTokenSource), cancelTokenSource.Token); | ||||||
| var client = new Server.Client(ip!, port); | ||||||
|
Comment on lines
+33
to
+36
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. Очень странно запускать сразу и сервер и клиент.Система сама с собой по сети общается? |
||||||
|
|
||||||
| for (int i = 2; i < args.Length; i++) | ||||||
| { | ||||||
| switch(args[i]) | ||||||
|
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
|
||||||
| { | ||||||
| case "list": | ||||||
| { | ||||||
| var (size, names) = await Task.Run(() => client.List(args[i + 1])); | ||||||
|
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
async-методы и так Task всегда возвращают, уже исполняющийся. Оборачивать их с помощью Task.Run нет смысла. Тут и много где ещё. |
||||||
| Console.WriteLine($"size : {size}"); | ||||||
| for (int j = 0; j < names.Count; j++) | ||||||
| { | ||||||
| Console.Write(names[j]); | ||||||
| Console.WriteLine(); | ||||||
| } | ||||||
| i++; | ||||||
| break; | ||||||
| } | ||||||
| case "get": | ||||||
| { | ||||||
| var(size, bytes) = await Task.Run(() => client.Get(args[i + 1])); | ||||||
| Console.WriteLine($"size : {size}"); | ||||||
| for (int j = 0; j < bytes.Length; j++) | ||||||
| { | ||||||
| Console.Write(bytes[j]); | ||||||
|
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. Не, надо бы в файл писать |
||||||
| } | ||||||
| Console.WriteLine(); | ||||||
| i++; | ||||||
| break; | ||||||
| } | ||||||
| default: | ||||||
| { | ||||||
| i++; | ||||||
| continue; | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| dewdewdewdwef wee v vev vjev dvied vd vdsv dvd vd vd df dfiv dfvedvbaev aevea beab deobed beb ervbew vv ebveivbe besba sD bdf bdf bdfbfdb df fdbfdb fd df df bjer jejberb ebe be rber bb boerivb er ibb erbervber vbrbvj jeb ev e e idfb fdivdfmvi mivdfvmidfvim mmidfvmiifvimfm idfmvmfdvmdfivmifimdimvimf mimdfivmdfiv miadmiviabjiaibvdafjibjid indfinvindfndfin idn idifdibijdfjbifd idfvjiijfbjidfaij idfbidfi d df bidf daf df fvdfvdfiiodfmo dfufdn ndfuudjivjdfbjiijoadfn adfinbdafibjvadfibjdafi iadjbjiadijbdaibnn idfiidfjbjidjibadijijodb idafbidjafjbidjoi dfjibdfibidfjij dfjivjdfjiboi dfivjdfbjidij dfijbjiodfjibdnirtbib inirjtnijrtjn ijtrbjiribr ibijbrtbiijtrbjrtbjiibrjibtrbtbijoiojriojiijijtij rtbtjibibdindinbi ninnitniintrhintinbnibntrnithtnr htrirtib jin ihtrjnb b bitrb ijb bijtbf brb rbb nbnjb tbnjtr btnb tbn tbntrjbnjnb btjnbtrjnbjtrbntrnbr btrjnbntbjtrb trjnbniorbnooithiorbirbj ibirbnoiernib |
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.
Пустые тэги не нужны