From 92c64504e1083f686bc74a3fe7b318730c0771c9 Mon Sep 17 00:00:00 2001 From: Artem Date: Sun, 22 Oct 2023 17:13:36 +0300 Subject: [PATCH 1/7] =?UTF-8?q?+=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82,=20+?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/FTPClient/Client.cs | 62 ++++++++ NewFTPServer/FTPClient/FTPClient.csproj | 10 ++ NewFTPServer/FTPClient/Program.cs | 8 + NewFTPServer/FTPServer/FTPServer.csproj | 10 ++ NewFTPServer/FTPServer/Program.cs | 5 + NewFTPServer/FTPServer/Server.cs | 192 ++++++++++++++++++++++++ NewFTPServer/NewFTPServer.sln | 31 ++++ 7 files changed, 318 insertions(+) create mode 100644 NewFTPServer/FTPClient/Client.cs create mode 100644 NewFTPServer/FTPClient/FTPClient.csproj create mode 100644 NewFTPServer/FTPClient/Program.cs create mode 100644 NewFTPServer/FTPServer/FTPServer.csproj create mode 100644 NewFTPServer/FTPServer/Program.cs create mode 100644 NewFTPServer/FTPServer/Server.cs create mode 100644 NewFTPServer/NewFTPServer.sln diff --git a/NewFTPServer/FTPClient/Client.cs b/NewFTPServer/FTPClient/Client.cs new file mode 100644 index 0000000..9a442fd --- /dev/null +++ b/NewFTPServer/FTPClient/Client.cs @@ -0,0 +1,62 @@ +using System.Net.Sockets; +using System.Text; + +namespace SimpleFTP; + +public class Client +{ + private static int _port; + private static string? _hostname; + + public Client(int port, string hostname) + { + _port = port; + _hostname = hostname; + Console.WriteLine("Client started!"); + } + + public async Task Get(string filePath) + { + if (_hostname == null) + { + throw new ArgumentNullException(); + } + + var client = new TcpClient(_hostname, _port); + + + var stream = client.GetStream(); + + await stream.WriteAsync(Encoding.UTF8.GetBytes("2 " + filePath + "\n")); + await stream.FlushAsync(); + + return await GetResultFromStream(stream, "Get"); + } + + public async Task List(string directoryPath) + { + if (_hostname == null) + { + throw new ArgumentNullException(); + } + + var client = new TcpClient(directoryPath, _port); + var stream = client.GetStream(); + + await stream.WriteAsync(Encoding.UTF8.GetBytes("1 " + directoryPath + "\n")); + await stream.FlushAsync(); + + return await GetResultFromStream(stream, "List"); + } + + private static async Task GetResultFromStream(NetworkStream stream, string method) + { + var buffer = new byte[4096]; + + var sizeResult = await stream.ReadAsync(buffer, 0, buffer.Length); + var result = new StringBuilder(); + result.Append(Encoding.UTF8.GetString(buffer, 0, sizeResult)); + + return result.ToString(); + } +} \ No newline at end of file diff --git a/NewFTPServer/FTPClient/FTPClient.csproj b/NewFTPServer/FTPClient/FTPClient.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/NewFTPServer/FTPClient/FTPClient.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/NewFTPServer/FTPClient/Program.cs b/NewFTPServer/FTPClient/Program.cs new file mode 100644 index 0000000..a4696e5 --- /dev/null +++ b/NewFTPServer/FTPClient/Program.cs @@ -0,0 +1,8 @@ +using SimpleFTP; + +var client = new Client(8888, "localhost"); + + +var result = await client.Get("../local.txt"); + +Console.WriteLine(result); \ No newline at end of file diff --git a/NewFTPServer/FTPServer/FTPServer.csproj b/NewFTPServer/FTPServer/FTPServer.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/NewFTPServer/FTPServer/FTPServer.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/NewFTPServer/FTPServer/Program.cs b/NewFTPServer/FTPServer/Program.cs new file mode 100644 index 0000000..3711bd4 --- /dev/null +++ b/NewFTPServer/FTPServer/Program.cs @@ -0,0 +1,5 @@ +using SimpleFTP; + +Server server = new SimpleFTP.Server("C:/", 8888); + +await server.Start(); \ No newline at end of file diff --git a/NewFTPServer/FTPServer/Server.cs b/NewFTPServer/FTPServer/Server.cs new file mode 100644 index 0000000..f29907d --- /dev/null +++ b/NewFTPServer/FTPServer/Server.cs @@ -0,0 +1,192 @@ +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace SimpleFTP; + +public class Server +{ + private static string? _locate; + private static TcpListener? _listener; + private static List? _clients; + private static CancellationTokenSource _cancellationToken; + private static List _tasks; + + public Server(string locate, int port) + { + if (locate == null) + { + throw new ArgumentNullException(); + } + _locate = locate; + _listener = new TcpListener(IPAddress.Any, port); + _cancellationToken = new CancellationTokenSource(); + _tasks = new List(); + _clients = new List(); + Console.WriteLine($"Server started on port: {port}"); + } + + public async Task Start() + { + if (_listener == null) + { + throw new ArgumentNullException(nameof(_listener)); + } + + if (_clients == null) + { + throw new ArgumentNullException(nameof(_clients)); + } + + + _listener.Start(); + try + { + while (!_cancellationToken.IsCancellationRequested) + { + var client = await _listener.AcceptTcpClientAsync(); + _clients.Add(client); + _tasks.Add(Listen(client)); + } + + Task.WaitAll(_tasks.ToArray()); + foreach (var client in _clients) + { + client.Dispose(); + client.Close(); + } + + _tasks.Clear(); + + _listener.Stop(); + } + finally + { + Stop(); + } + } + + private static Task Listen(TcpClient client) + { + return Task.Run(async () => + { + if (client == null) + { + throw new ArgumentNullException("client"); + } + + var stream = client.GetStream(); + var buffer = new byte[4096]; + + if (!_cancellationToken.IsCancellationRequested) + { + var sizeCommand = await stream.ReadAsync(buffer, 0, buffer.Length); + var command = new StringBuilder(); + command.Append(Encoding.UTF8.GetString(buffer, 0, sizeCommand)); + + var stringCommand = command.ToString(); + + if (command[0] == '1') + { + List(stringCommand.TrimStart('1', ' '), stream); + } + else + { + Get(stringCommand.TrimStart('2', ' '), stream); + } + } + } + ); + } + + public void Stop() + { + if (_listener != null) + { + _cancellationToken.Cancel(); + } + } + + private static void Get(string directory, NetworkStream stream) + { + Task.Run(async () => + { + if (_locate == null) + { + throw new NullReferenceException(); + } + + var path = Path.Combine(_locate, directory);// + if (!File.Exists(path)) + { + await stream.WriteAsync(Encoding.UTF8.GetBytes("-1")); + } + else + { + var text = await File.ReadAllTextAsync(path); + await stream.WriteAsync(Encoding.UTF8.GetBytes(text)); + } + }); + } + private static void List(string directory, NetworkStream stream) + { + Task.Run(async () => + { + if (_locate == null) + { + throw new NullReferenceException(); + } + + var path = Path.GetFullPath(_locate, directory); + if (!File.Exists(path)) + { + await stream.WriteAsync(Encoding.UTF8.GetBytes("-1")); + } + else + { + var filesAndDirectories = new StringBuilder(); + var directories = Directory.GetFiles(path); + + var sizeFilesAndDirectories = directories.Length; + + foreach (var directory in directories) + { + filesAndDirectories.Append(" " + directory + " true"); + } + + var files = Directory.GetFiles(path); + sizeFilesAndDirectories += files.Length; + + foreach (var file in files) + { + filesAndDirectories.Append(" " + file + "false"); + } + + filesAndDirectories.Append('\n'); + filesAndDirectories.Insert(0, sizeFilesAndDirectories.ToString()); + + await stream.WriteAsync(Encoding.UTF8.GetBytes(filesAndDirectories.ToString())); + } + }); + } + + /* + private static void Get(NetworkStream stream, TcpClient client) + { + Task.Run(async () => + { + var writer = new StreamWriter(stream) { AutoFlush = true }; + var allText = new StringBuilder(); + byte[] data = new byte[512]; + var socket = _listener.AcceptSocket(); + int sizeData = 0; + do + { + sizeData = await stream.ReadAsync(data, _cancellationToken); + allText.Append(Encoding.UTF8.GetString(data, 0, sizeData)); + } while (sizeData > 0); + }); + } + */ + +} \ No newline at end of file diff --git a/NewFTPServer/NewFTPServer.sln b/NewFTPServer/NewFTPServer.sln new file mode 100644 index 0000000..a8606f4 --- /dev/null +++ b/NewFTPServer/NewFTPServer.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33403.182 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FTPServer", "FTPServer\FTPServer.csproj", "{D9E2CBBA-EE73-4149-A774-70DC12B4886E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FTPClient", "FTPClient\FTPClient.csproj", "{1C09410D-0CEF-4464-8162-7F4F16EC5066}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D9E2CBBA-EE73-4149-A774-70DC12B4886E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9E2CBBA-EE73-4149-A774-70DC12B4886E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9E2CBBA-EE73-4149-A774-70DC12B4886E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9E2CBBA-EE73-4149-A774-70DC12B4886E}.Release|Any CPU.Build.0 = Release|Any CPU + {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {39F5B087-17DF-4DAF-9AC5-B12D1F761E54} + EndGlobalSection +EndGlobal From 4bfb66b8bff1f370885679e9bbcfe8a0545202f3 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Oct 2023 11:33:04 +0300 Subject: [PATCH 2/7] =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=82=D1=8B,=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/FTPClient/Client.cs | 16 +++- NewFTPServer/FTPServer/Server.cs | 79 ++++++++++------- NewFTPServer/NewFTPServer.sln | 10 ++- NewFTPServer/TestsFTP/TestsFTP.cs | 120 ++++++++++++++++++++++++++ NewFTPServer/TestsFTP/TestsFTP.csproj | 24 ++++++ NewFTPServer/TestsFTP/Usings.cs | 1 + 6 files changed, 215 insertions(+), 35 deletions(-) create mode 100644 NewFTPServer/TestsFTP/TestsFTP.cs create mode 100644 NewFTPServer/TestsFTP/TestsFTP.csproj create mode 100644 NewFTPServer/TestsFTP/Usings.cs diff --git a/NewFTPServer/FTPClient/Client.cs b/NewFTPServer/FTPClient/Client.cs index 9a442fd..2a4774e 100644 --- a/NewFTPServer/FTPClient/Client.cs +++ b/NewFTPServer/FTPClient/Client.cs @@ -3,11 +3,17 @@ namespace SimpleFTP; +/// +/// FTP Client implementation class +/// public class Client { private static int _port; private static string? _hostname; + /// + /// Class constructor + /// public Client(int port, string hostname) { _port = port; @@ -15,6 +21,10 @@ public Client(int port, string hostname) Console.WriteLine("Client started!"); } + /// + /// Downloading a file from the server + /// + /// The relative path of the file from the specified path on the server public async Task Get(string filePath) { if (_hostname == null) @@ -33,6 +43,10 @@ public async Task Get(string filePath) return await GetResultFromStream(stream, "Get"); } + /// + /// Listing files in a directory on the server + /// + /// The relative path of the directory from the specified path on the server public async Task List(string directoryPath) { if (_hostname == null) @@ -40,7 +54,7 @@ public async Task List(string directoryPath) throw new ArgumentNullException(); } - var client = new TcpClient(directoryPath, _port); + var client = new TcpClient(_hostname, _port); var stream = client.GetStream(); await stream.WriteAsync(Encoding.UTF8.GetBytes("1 " + directoryPath + "\n")); diff --git a/NewFTPServer/FTPServer/Server.cs b/NewFTPServer/FTPServer/Server.cs index f29907d..5d81a7a 100644 --- a/NewFTPServer/FTPServer/Server.cs +++ b/NewFTPServer/FTPServer/Server.cs @@ -1,17 +1,25 @@ -using System.Net; +using System.Diagnostics.CodeAnalysis; +using System.Net; using System.Net.Sockets; using System.Text; namespace SimpleFTP; +/// +/// A class that implements an FTP server +/// public class Server { private static string? _locate; private static TcpListener? _listener; private static List? _clients; - private static CancellationTokenSource _cancellationToken; - private static List _tasks; + private static CancellationTokenSource? _cancellationToken; + private static List? _tasks; + /// + /// Class constructor + /// + /// The absolute path of the server location public Server(string locate, int port) { if (locate == null) @@ -26,6 +34,9 @@ public Server(string locate, int port) Console.WriteLine($"Server started on port: {port}"); } + /// + /// Starting the server + /// public async Task Start() { if (_listener == null) @@ -38,6 +49,15 @@ public async Task Start() throw new ArgumentNullException(nameof(_clients)); } + if (_tasks == null) + { + throw new ArgumentNullException(nameof(_tasks)); + } + + if (_cancellationToken == null) + { + throw new ArgumentNullException(nameof(_cancellationToken)); + } _listener.Start(); try @@ -68,6 +88,11 @@ public async Task Start() private static Task Listen(TcpClient client) { + if (_cancellationToken == null) + { + throw new ArgumentNullException(nameof(_cancellationToken)); + } + return Task.Run(async () => { if (client == null) @@ -88,20 +113,23 @@ private static Task Listen(TcpClient client) if (command[0] == '1') { - List(stringCommand.TrimStart('1', ' '), stream); + List(stringCommand.TrimStart('1', ' ').TrimEnd('\n'), stream); } else { - Get(stringCommand.TrimStart('2', ' '), stream); + Get(stringCommand.TrimStart('2', ' ').TrimEnd('\n'), stream); } } } ); } + /// + /// Server shutdown + /// public void Stop() { - if (_listener != null) + if (_listener != null && _cancellationToken != null) { _cancellationToken.Cancel(); } @@ -116,7 +144,10 @@ private static void Get(string directory, NetworkStream stream) throw new NullReferenceException(); } - var path = Path.Combine(_locate, directory);// + string combinePath = Path.Combine(_locate, directory); + DirectoryInfo info = new DirectoryInfo(combinePath); + var path = info.FullName; + if (!File.Exists(path)) { await stream.WriteAsync(Encoding.UTF8.GetBytes("-1")); @@ -124,6 +155,7 @@ private static void Get(string directory, NetworkStream stream) else { var text = await File.ReadAllTextAsync(path); + text = text.Insert(0, text.Length.ToString() + " "); await stream.WriteAsync(Encoding.UTF8.GetBytes(text)); } }); @@ -136,22 +168,25 @@ private static void List(string directory, NetworkStream stream) { throw new NullReferenceException(); } + + string combinePath = Path.Combine(_locate, directory); + DirectoryInfo info = new DirectoryInfo(combinePath); + var path = info.FullName; - var path = Path.GetFullPath(_locate, directory); - if (!File.Exists(path)) + if (!Directory.Exists(path)) { await stream.WriteAsync(Encoding.UTF8.GetBytes("-1")); } else { var filesAndDirectories = new StringBuilder(); - var directories = Directory.GetFiles(path); + var directories = Directory.GetDirectories(path); var sizeFilesAndDirectories = directories.Length; foreach (var directory in directories) { - filesAndDirectories.Append(" " + directory + " true"); + filesAndDirectories.Append(" " + directory.Substring(directory.LastIndexOf('\\') + 1) + " true"); } var files = Directory.GetFiles(path); @@ -159,7 +194,7 @@ private static void List(string directory, NetworkStream stream) foreach (var file in files) { - filesAndDirectories.Append(" " + file + "false"); + filesAndDirectories.Append(" " + file.Substring(file.LastIndexOf('\\') + 1) + " false"); } filesAndDirectories.Append('\n'); @@ -169,24 +204,4 @@ private static void List(string directory, NetworkStream stream) } }); } - - /* - private static void Get(NetworkStream stream, TcpClient client) - { - Task.Run(async () => - { - var writer = new StreamWriter(stream) { AutoFlush = true }; - var allText = new StringBuilder(); - byte[] data = new byte[512]; - var socket = _listener.AcceptSocket(); - int sizeData = 0; - do - { - sizeData = await stream.ReadAsync(data, _cancellationToken); - allText.Append(Encoding.UTF8.GetString(data, 0, sizeData)); - } while (sizeData > 0); - }); - } - */ - } \ No newline at end of file diff --git a/NewFTPServer/NewFTPServer.sln b/NewFTPServer/NewFTPServer.sln index a8606f4..d32f6ba 100644 --- a/NewFTPServer/NewFTPServer.sln +++ b/NewFTPServer/NewFTPServer.sln @@ -3,9 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33403.182 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FTPServer", "FTPServer\FTPServer.csproj", "{D9E2CBBA-EE73-4149-A774-70DC12B4886E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FTPServer", "FTPServer\FTPServer.csproj", "{D9E2CBBA-EE73-4149-A774-70DC12B4886E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FTPClient", "FTPClient\FTPClient.csproj", "{1C09410D-0CEF-4464-8162-7F4F16EC5066}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FTPClient", "FTPClient\FTPClient.csproj", "{1C09410D-0CEF-4464-8162-7F4F16EC5066}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsFTP", "TestsFTP\TestsFTP.csproj", "{98F4C7F9-B324-4D82-AE9B-965025AF9B6C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Debug|Any CPU.Build.0 = Debug|Any CPU {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C09410D-0CEF-4464-8162-7F4F16EC5066}.Release|Any CPU.Build.0 = Release|Any CPU + {98F4C7F9-B324-4D82-AE9B-965025AF9B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98F4C7F9-B324-4D82-AE9B-965025AF9B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98F4C7F9-B324-4D82-AE9B-965025AF9B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98F4C7F9-B324-4D82-AE9B-965025AF9B6C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NewFTPServer/TestsFTP/TestsFTP.cs b/NewFTPServer/TestsFTP/TestsFTP.cs new file mode 100644 index 0000000..7543d8f --- /dev/null +++ b/NewFTPServer/TestsFTP/TestsFTP.cs @@ -0,0 +1,120 @@ +namespace TestsFTP; + +using Microsoft.VisualBasic; +using SimpleFTP; + +public class Tests +{ + Server server = new SimpleFTP.Server(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsFTP"), 8888); + + [Test] + public async Task GettingInformationFromANonExistentFile() + { + var client = new Client(8888, "localhost"); + + if (server == null) + { + Assert.Fail(); + return; + } + + if (client == null) + { + Assert.Fail(); + return; + } + + var serverThread = new Thread(async () => await server.Start()); + + serverThread.Start(); + + var result = await client.Get("./test.txt"); + + Assert.That(result, Is.EqualTo("-1")); + + serverThread.Join(); + } + + [Test] + public async Task GettingInformationFromExistentFile() + { + var client = new Client(8888, "localhost"); + + if (server == null) + { + Assert.Fail(); + return; + } + + if (client == null) + { + Assert.Fail(); + return; + } + + var serverThread = new Thread(async () => await server.Start()); + + serverThread.Start(); + + var result = await client.Get("./testForGet.txt"); + + Assert.That(result, Is.EqualTo("3 123")); + + serverThread.Join(); + } + + [Test] + public async Task GettingInformationFromNonExistentDirectory() + { + var client = new Client(8888, "localhost"); + + if (server == null) + { + Assert.Fail(); + return; + } + + if (client == null) + { + Assert.Fail(); + return; + } + + var serverThread = new Thread(async () => await server.Start()); + + serverThread.Start(); + + var result = await client.List("./testForLister"); + + Assert.That(result, Is.EqualTo("-1")); + + serverThread.Join(); + } + + [Test] + public async Task GettingInformationFromExistentDirectory() + { + var client = new Client(8888, "localhost"); + + if (server == null) + { + Assert.Fail(); + return; + } + + if (client == null) + { + Assert.Fail(); + return; + } + + var serverThread = new Thread(async () => await server.Start()); + + serverThread.Start(); + + var result = await client.List("./testForList"); + + Assert.That(result, Is.EqualTo("3 test3 true test1.txt false test2.txt false\n")); + serverThread.Join(); + } +} \ No newline at end of file diff --git a/NewFTPServer/TestsFTP/TestsFTP.csproj b/NewFTPServer/TestsFTP/TestsFTP.csproj new file mode 100644 index 0000000..a613fd4 --- /dev/null +++ b/NewFTPServer/TestsFTP/TestsFTP.csproj @@ -0,0 +1,24 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + + diff --git a/NewFTPServer/TestsFTP/Usings.cs b/NewFTPServer/TestsFTP/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/NewFTPServer/TestsFTP/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file From 187c914a922b6f38aa1b677a93a9d106392d968d Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Oct 2023 11:43:22 +0300 Subject: [PATCH 3/7] =?UTF-8?q?=D0=A4=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForGet.txt | 1 + .../TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test1.txt | 0 .../TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test2.txt | 0 .../bin/Debug/net7.0/TestsFTP/testForList/test3/test4.txt | 0 4 files changed, 1 insertion(+) create mode 100644 NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForGet.txt create mode 100644 NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test1.txt create mode 100644 NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test2.txt create mode 100644 NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test3/test4.txt diff --git a/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForGet.txt b/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForGet.txt new file mode 100644 index 0000000..d800886 --- /dev/null +++ b/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForGet.txt @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test1.txt b/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test1.txt new file mode 100644 index 0000000..e69de29 diff --git a/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test2.txt b/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test2.txt new file mode 100644 index 0000000..e69de29 diff --git a/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test3/test4.txt b/NewFTPServer/TestsFTP/bin/Debug/net7.0/TestsFTP/testForList/test3/test4.txt new file mode 100644 index 0000000..e69de29 From 84a9ecbe3b1741cd5d48e6d04610559495c97f92 Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 9 Dec 2023 18:59:04 +0300 Subject: [PATCH 4/7] =?UTF-8?q?=D0=A0=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/FTPClient/Client.cs | 43 +++++++---- NewFTPServer/FTPClient/Program.cs | 3 - NewFTPServer/FTPServer/Program.cs | 15 +++- NewFTPServer/FTPServer/Server.cs | 115 +++++++++++++----------------- NewFTPServer/TestsFTP/TestsFTP.cs | 98 ++++--------------------- 5 files changed, 104 insertions(+), 170 deletions(-) diff --git a/NewFTPServer/FTPClient/Client.cs b/NewFTPServer/FTPClient/Client.cs index 2a4774e..434312f 100644 --- a/NewFTPServer/FTPClient/Client.cs +++ b/NewFTPServer/FTPClient/Client.cs @@ -8,16 +8,16 @@ namespace SimpleFTP; /// public class Client { - private static int _port; - private static string? _hostname; + private static int port; + private static string? hostname; /// /// Class constructor /// public Client(int port, string hostname) { - _port = port; - _hostname = hostname; + Client.port = port; + Client.hostname = hostname; Console.WriteLine("Client started!"); } @@ -27,43 +27,45 @@ public Client(int port, string hostname) /// The relative path of the file from the specified path on the server public async Task Get(string filePath) { - if (_hostname == null) + if (hostname == null) { throw new ArgumentNullException(); } - var client = new TcpClient(_hostname, _port); - + var client = new TcpClient(); + await client.ConnectAsync(hostname, port); var stream = client.GetStream(); - await stream.WriteAsync(Encoding.UTF8.GetBytes("2 " + filePath + "\n")); + await stream.WriteAsync(Encoding.UTF8.GetBytes($"2 {filePath}\n")); await stream.FlushAsync(); - return await GetResultFromStream(stream, "Get"); + return await GetResultFromStreamForGet(stream); } /// /// Listing files in a directory on the server /// /// The relative path of the directory from the specified path on the server - public async Task List(string directoryPath) + public async Task List(string directoryPath) { - if (_hostname == null) + if (hostname == null) { throw new ArgumentNullException(); } - var client = new TcpClient(_hostname, _port); + var client = new TcpClient(); + await client.ConnectAsync(hostname, port); + var stream = client.GetStream(); - await stream.WriteAsync(Encoding.UTF8.GetBytes("1 " + directoryPath + "\n")); + await stream.WriteAsync(Encoding.UTF8.GetBytes($"1 {directoryPath}\n")); await stream.FlushAsync(); - return await GetResultFromStream(stream, "List"); + return await GetResultFromStreamForList(stream); } - private static async Task GetResultFromStream(NetworkStream stream, string method) + private static async Task GetResultFromStreamForGet(NetworkStream stream) { var buffer = new byte[4096]; @@ -73,4 +75,15 @@ private static async Task GetResultFromStream(NetworkStream stream, stri return result.ToString(); } + + private static async Task GetResultFromStreamForList(NetworkStream stream) + { + var reader = new StreamReader(stream, Encoding.UTF8); + var result = await reader.ReadLineAsync(); + if (result != null) + { + result.Append('\n'); + } + return result; + } } \ No newline at end of file diff --git a/NewFTPServer/FTPClient/Program.cs b/NewFTPServer/FTPClient/Program.cs index a4696e5..ed17c1a 100644 --- a/NewFTPServer/FTPClient/Program.cs +++ b/NewFTPServer/FTPClient/Program.cs @@ -1,8 +1,5 @@ using SimpleFTP; var client = new Client(8888, "localhost"); - - var result = await client.Get("../local.txt"); - Console.WriteLine(result); \ No newline at end of file diff --git a/NewFTPServer/FTPServer/Program.cs b/NewFTPServer/FTPServer/Program.cs index 3711bd4..e10f04c 100644 --- a/NewFTPServer/FTPServer/Program.cs +++ b/NewFTPServer/FTPServer/Program.cs @@ -1,5 +1,16 @@ using SimpleFTP; -Server server = new SimpleFTP.Server("C:/", 8888); +class Program +{ + static async Task Main() + { + Server server = new SimpleFTP.Server("C:/", 8888); -await server.Start(); \ No newline at end of file + Task serverTask = Task.Run(async () => await server.Start()); + + Console.WriteLine("нажмите на любую клавишу для остановки серверка"); + Console.ReadKey(); + + server.Stop(); + } +} \ No newline at end of file diff --git a/NewFTPServer/FTPServer/Server.cs b/NewFTPServer/FTPServer/Server.cs index 5d81a7a..e0cdb9e 100644 --- a/NewFTPServer/FTPServer/Server.cs +++ b/NewFTPServer/FTPServer/Server.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.CodeAnalysis; +using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.Sockets; using System.Text; @@ -10,11 +11,11 @@ namespace SimpleFTP; /// public class Server { - private static string? _locate; - private static TcpListener? _listener; - private static List? _clients; - private static CancellationTokenSource? _cancellationToken; - private static List? _tasks; + private static string? locate; + private static TcpListener? listener; + private static List? clients; + private static CancellationTokenSource? cancellationToken; + private static List? tasks; /// /// Class constructor @@ -26,11 +27,11 @@ public Server(string locate, int port) { throw new ArgumentNullException(); } - _locate = locate; - _listener = new TcpListener(IPAddress.Any, port); - _cancellationToken = new CancellationTokenSource(); - _tasks = new List(); - _clients = new List(); + Server.locate = locate; + listener = new TcpListener(IPAddress.Any, port); + cancellationToken = new CancellationTokenSource(); + tasks = new List(); + clients = new List(); Console.WriteLine($"Server started on port: {port}"); } @@ -39,58 +40,36 @@ public Server(string locate, int port) /// public async Task Start() { - if (_listener == null) + if (listener == null || clients == null + || tasks == null || cancellationToken == null) { - throw new ArgumentNullException(nameof(_listener)); + throw new ArgumentNullException(); } - if (_clients == null) + listener.Start(); + while (!cancellationToken.IsCancellationRequested) { - throw new ArgumentNullException(nameof(_clients)); + var client = await listener.AcceptTcpClientAsync(cancellationToken.Token); + clients.Add(client); + tasks.Add(Listen(client)); } - if (_tasks == null) + Task.WaitAll(tasks.ToArray()); + foreach (var client in clients) { - throw new ArgumentNullException(nameof(_tasks)); + client.Close(); } - if (_cancellationToken == null) - { - throw new ArgumentNullException(nameof(_cancellationToken)); - } + tasks.Clear(); - _listener.Start(); - try - { - while (!_cancellationToken.IsCancellationRequested) - { - var client = await _listener.AcceptTcpClientAsync(); - _clients.Add(client); - _tasks.Add(Listen(client)); - } - - Task.WaitAll(_tasks.ToArray()); - foreach (var client in _clients) - { - client.Dispose(); - client.Close(); - } - - _tasks.Clear(); - - _listener.Stop(); - } - finally - { - Stop(); - } + listener.Stop(); } private static Task Listen(TcpClient client) { - if (_cancellationToken == null) + if (cancellationToken == null) { - throw new ArgumentNullException(nameof(_cancellationToken)); + throw new ArgumentNullException(nameof(cancellationToken)); } return Task.Run(async () => @@ -101,23 +80,24 @@ private static Task Listen(TcpClient client) } var stream = client.GetStream(); - var buffer = new byte[4096]; - if (!_cancellationToken.IsCancellationRequested) + if (!cancellationToken.IsCancellationRequested) { - var sizeCommand = await stream.ReadAsync(buffer, 0, buffer.Length); - var command = new StringBuilder(); - command.Append(Encoding.UTF8.GetString(buffer, 0, sizeCommand)); + var reader = new StreamReader(stream, Encoding.UTF8); + var stringCommand = await reader.ReadLineAsync(); - var stringCommand = command.ToString(); + if (stringCommand == null) + { + throw new InvalidOperationException(); + } - if (command[0] == '1') + if (stringCommand[0] == '1') { - List(stringCommand.TrimStart('1', ' ').TrimEnd('\n'), stream); + List(stringCommand.TrimStart('1', ' '), stream); } else { - Get(stringCommand.TrimStart('2', ' ').TrimEnd('\n'), stream); + Get(stringCommand.TrimStart('2', ' '), stream); } } } @@ -129,9 +109,9 @@ private static Task Listen(TcpClient client) /// public void Stop() { - if (_listener != null && _cancellationToken != null) + if (listener != null && cancellationToken != null) { - _cancellationToken.Cancel(); + cancellationToken.Cancel(); } } @@ -139,12 +119,12 @@ private static void Get(string directory, NetworkStream stream) { Task.Run(async () => { - if (_locate == null) + if (locate == null) { throw new NullReferenceException(); } - string combinePath = Path.Combine(_locate, directory); + string combinePath = Path.Combine(locate, directory); DirectoryInfo info = new DirectoryInfo(combinePath); var path = info.FullName; @@ -154,9 +134,10 @@ private static void Get(string directory, NetworkStream stream) } else { - var text = await File.ReadAllTextAsync(path); - text = text.Insert(0, text.Length.ToString() + " "); - await stream.WriteAsync(Encoding.UTF8.GetBytes(text)); + var textBytes = File.ReadAllBytes(path); + string text = Encoding.UTF8.GetString(textBytes); + string newText = $"{textBytes.Length} {text}"; + await stream.WriteAsync(Encoding.UTF8.GetBytes(newText)); } }); } @@ -164,18 +145,18 @@ private static void List(string directory, NetworkStream stream) { Task.Run(async () => { - if (_locate == null) + if (locate == null) { throw new NullReferenceException(); } - string combinePath = Path.Combine(_locate, directory); + string combinePath = Path.Combine(locate, directory); DirectoryInfo info = new DirectoryInfo(combinePath); var path = info.FullName; if (!Directory.Exists(path)) { - await stream.WriteAsync(Encoding.UTF8.GetBytes("-1")); + await stream.WriteAsync(Encoding.UTF8.GetBytes("-1\n")); } else { diff --git a/NewFTPServer/TestsFTP/TestsFTP.cs b/NewFTPServer/TestsFTP/TestsFTP.cs index 7543d8f..018954a 100644 --- a/NewFTPServer/TestsFTP/TestsFTP.cs +++ b/NewFTPServer/TestsFTP/TestsFTP.cs @@ -1,120 +1,52 @@ namespace TestsFTP; - -using Microsoft.VisualBasic; using SimpleFTP; public class Tests { Server server = new SimpleFTP.Server(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsFTP"), 8888); + Client client = new Client(8888, "localhost"); - [Test] - public async Task GettingInformationFromANonExistentFile() + [SetUp] + public void SetUp() { - var client = new Client(8888, "localhost"); - - if (server == null) - { - Assert.Fail(); - return; - } - - if (client == null) + if (server == null || client == null) { - Assert.Fail(); return; } + var serverTask = Task.Run(server.Start); + } - var serverThread = new Thread(async () => await server.Start()); - - serverThread.Start(); - + [Test] + public async Task GettingInformationFromANonExistentFile() + { var result = await client.Get("./test.txt"); - Assert.That(result, Is.EqualTo("-1")); - - serverThread.Join(); } [Test] public async Task GettingInformationFromExistentFile() { - var client = new Client(8888, "localhost"); - - if (server == null) - { - Assert.Fail(); - return; - } - - if (client == null) - { - Assert.Fail(); - return; - } - - var serverThread = new Thread(async () => await server.Start()); - - serverThread.Start(); - var result = await client.Get("./testForGet.txt"); - Assert.That(result, Is.EqualTo("3 123")); - - serverThread.Join(); } [Test] public async Task GettingInformationFromNonExistentDirectory() { - var client = new Client(8888, "localhost"); - - if (server == null) - { - Assert.Fail(); - return; - } - - if (client == null) - { - Assert.Fail(); - return; - } - - var serverThread = new Thread(async () => await server.Start()); - - serverThread.Start(); - var result = await client.List("./testForLister"); - Assert.That(result, Is.EqualTo("-1")); - - serverThread.Join(); } [Test] public async Task GettingInformationFromExistentDirectory() { - var client = new Client(8888, "localhost"); - - if (server == null) - { - Assert.Fail(); - return; - } - - if (client == null) - { - Assert.Fail(); - return; - } - - var serverThread = new Thread(async () => await server.Start()); - - serverThread.Start(); - var result = await client.List("./testForList"); + Assert.That(result, Is.EqualTo("3 test3 true test1.txt false test2.txt false")); + } - Assert.That(result, Is.EqualTo("3 test3 true test1.txt false test2.txt false\n")); - serverThread.Join(); + [TearDown] + public void Teardown() + { + server.Stop(); } } \ No newline at end of file From 5b37af0d27baad0bc018a7210139c419b505eef3 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 27 Dec 2023 13:48:28 +0300 Subject: [PATCH 5/7] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/FTPServer/Server.cs | 5 ++--- NewFTPServer/TestsFTP/TestsFTP.cs | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/NewFTPServer/FTPServer/Server.cs b/NewFTPServer/FTPServer/Server.cs index e0cdb9e..b77f8ef 100644 --- a/NewFTPServer/FTPServer/Server.cs +++ b/NewFTPServer/FTPServer/Server.cs @@ -1,6 +1,4 @@ -using System.Collections; -using System.Diagnostics.CodeAnalysis; -using System.Net; +using System.Net; using System.Net.Sockets; using System.Text; @@ -49,6 +47,7 @@ public async Task Start() listener.Start(); while (!cancellationToken.IsCancellationRequested) { + Console.WriteLine("Жду клиента"); var client = await listener.AcceptTcpClientAsync(cancellationToken.Token); clients.Add(client); tasks.Add(Listen(client)); diff --git a/NewFTPServer/TestsFTP/TestsFTP.cs b/NewFTPServer/TestsFTP/TestsFTP.cs index 018954a..41fdea2 100644 --- a/NewFTPServer/TestsFTP/TestsFTP.cs +++ b/NewFTPServer/TestsFTP/TestsFTP.cs @@ -5,43 +5,43 @@ public class Tests { Server server = new SimpleFTP.Server(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsFTP"), 8888); Client client = new Client(8888, "localhost"); - + [SetUp] public void SetUp() { - if (server == null || client == null) + if (server == null) { return; } - var serverTask = Task.Run(server.Start); + Task.Run(() => server.Start()); } [Test] - public async Task GettingInformationFromANonExistentFile() + public void GettingInformationFromANonExistentFile() { - var result = await client.Get("./test.txt"); - Assert.That(result, Is.EqualTo("-1")); + var result = client.Get("./test.txt"); + Assert.That(result.Result, Is.EqualTo("-1")); } [Test] - public async Task GettingInformationFromExistentFile() + public void GettingInformationFromExistentFile() { - var result = await client.Get("./testForGet.txt"); - Assert.That(result, Is.EqualTo("3 123")); + var result = client.Get("./testForGet.txt"); + Assert.That(result.Result, Is.EqualTo("3 123")); } [Test] - public async Task GettingInformationFromNonExistentDirectory() + public void GettingInformationFromNonExistentDirectory() { - var result = await client.List("./testForLister"); - Assert.That(result, Is.EqualTo("-1")); + var result = client.List("./testForLister"); + Assert.That(result.Result, Is.EqualTo("-1")); } [Test] - public async Task GettingInformationFromExistentDirectory() + public void GettingInformationFromExistentDirectory() { - var result = await client.List("./testForList"); - Assert.That(result, Is.EqualTo("3 test3 true test1.txt false test2.txt false")); + var result = client.List("./testForList"); + Assert.That(result.Result, Is.EqualTo("3 test3 true test1.txt false test2.txt false")); } [TearDown] From 8875ccdaac2e6a54fcd40a3c600a582af9ae78cc Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 27 Dec 2023 14:23:06 +0300 Subject: [PATCH 6/7] =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/FTPServer/Server.cs | 12 ++++++------ NewFTPServer/TestsFTP/TestsFTP.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/NewFTPServer/FTPServer/Server.cs b/NewFTPServer/FTPServer/Server.cs index b77f8ef..43e253a 100644 --- a/NewFTPServer/FTPServer/Server.cs +++ b/NewFTPServer/FTPServer/Server.cs @@ -26,11 +26,10 @@ public Server(string locate, int port) throw new ArgumentNullException(); } Server.locate = locate; - listener = new TcpListener(IPAddress.Any, port); - cancellationToken = new CancellationTokenSource(); - tasks = new List(); - clients = new List(); - Console.WriteLine($"Server started on port: {port}"); + listener = new(IPAddress.Any, port); + cancellationToken = new(); + tasks = new(); + clients = new(); } /// @@ -45,9 +44,10 @@ public async Task Start() } listener.Start(); + Console.WriteLine("Server started working"); while (!cancellationToken.IsCancellationRequested) { - Console.WriteLine("Жду клиента"); + Console.WriteLine("Waiting a client"); var client = await listener.AcceptTcpClientAsync(cancellationToken.Token); clients.Add(client); tasks.Add(Listen(client)); diff --git a/NewFTPServer/TestsFTP/TestsFTP.cs b/NewFTPServer/TestsFTP/TestsFTP.cs index 41fdea2..f61a7ca 100644 --- a/NewFTPServer/TestsFTP/TestsFTP.cs +++ b/NewFTPServer/TestsFTP/TestsFTP.cs @@ -3,8 +3,8 @@ namespace TestsFTP; public class Tests { - Server server = new SimpleFTP.Server(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsFTP"), 8888); - Client client = new Client(8888, "localhost"); + Server server = new SimpleFTP.Server(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsFTP"), 7777); + Client client = new Client(7777, "localhost"); [SetUp] public void SetUp() From c566081e56f52b1446989a19660bb223ef1f688f Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 28 Dec 2023 19:34:48 +0300 Subject: [PATCH 7/7] =?UTF-8?q?=D0=A7=D0=B0=D1=81=D1=82=D1=8C=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewFTPServer/FTPServer/Server.cs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/NewFTPServer/FTPServer/Server.cs b/NewFTPServer/FTPServer/Server.cs index 43e253a..c8e70ce 100644 --- a/NewFTPServer/FTPServer/Server.cs +++ b/NewFTPServer/FTPServer/Server.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Diagnostics; +using System.Net; using System.Net.Sockets; using System.Text; @@ -68,6 +69,7 @@ private static Task Listen(TcpClient client) { if (cancellationToken == null) { + Stop(); throw new ArgumentNullException(nameof(cancellationToken)); } @@ -75,6 +77,7 @@ private static Task Listen(TcpClient client) { if (client == null) { + Stop(); throw new ArgumentNullException("client"); } @@ -87,6 +90,8 @@ private static Task Listen(TcpClient client) if (stringCommand == null) { + stream.Close(); + Stop(); throw new InvalidOperationException(); } @@ -106,7 +111,7 @@ private static Task Listen(TcpClient client) /// /// Server shutdown /// - public void Stop() + public static void Stop() { if (listener != null && cancellationToken != null) { @@ -120,6 +125,8 @@ private static void Get(string directory, NetworkStream stream) { if (locate == null) { + stream.Close(); + Stop(); throw new NullReferenceException(); } @@ -134,10 +141,10 @@ private static void Get(string directory, NetworkStream stream) else { var textBytes = File.ReadAllBytes(path); - string text = Encoding.UTF8.GetString(textBytes); - string newText = $"{textBytes.Length} {text}"; - await stream.WriteAsync(Encoding.UTF8.GetBytes(newText)); + await stream.WriteAsync(Encoding.UTF8.GetBytes($"{textBytes.Length} ")); + await stream.WriteAsync(textBytes); } + stream.Close(); }); } private static void List(string directory, NetworkStream stream) @@ -146,6 +153,8 @@ private static void List(string directory, NetworkStream stream) { if (locate == null) { + stream.Close(); + Stop(); throw new NullReferenceException(); } @@ -182,6 +191,7 @@ private static void List(string directory, NetworkStream stream) await stream.WriteAsync(Encoding.UTF8.GetBytes(filesAndDirectories.ToString())); } + stream.Close(); }); } } \ No newline at end of file