diff --git a/NewFTPServer/FTPClient/Client.cs b/NewFTPServer/FTPClient/Client.cs
new file mode 100644
index 0000000..434312f
--- /dev/null
+++ b/NewFTPServer/FTPClient/Client.cs
@@ -0,0 +1,89 @@
+using System.Net.Sockets;
+using System.Text;
+
+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)
+ {
+ Client.port = port;
+ Client.hostname = 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)
+ {
+ throw new ArgumentNullException();
+ }
+
+ var client = new TcpClient();
+ await client.ConnectAsync(hostname, port);
+
+ var stream = client.GetStream();
+
+ await stream.WriteAsync(Encoding.UTF8.GetBytes($"2 {filePath}\n"));
+ await stream.FlushAsync();
+
+ 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)
+ {
+ if (hostname == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ var client = new TcpClient();
+ await client.ConnectAsync(hostname, port);
+
+ var stream = client.GetStream();
+
+ await stream.WriteAsync(Encoding.UTF8.GetBytes($"1 {directoryPath}\n"));
+ await stream.FlushAsync();
+
+ return await GetResultFromStreamForList(stream);
+ }
+
+ private static async Task GetResultFromStreamForGet(NetworkStream stream)
+ {
+ 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();
+ }
+
+ 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/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..ed17c1a
--- /dev/null
+++ b/NewFTPServer/FTPClient/Program.cs
@@ -0,0 +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/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..e10f04c
--- /dev/null
+++ b/NewFTPServer/FTPServer/Program.cs
@@ -0,0 +1,16 @@
+using SimpleFTP;
+
+class Program
+{
+ static async Task Main()
+ {
+ Server server = new SimpleFTP.Server("C:/", 8888);
+
+ 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
new file mode 100644
index 0000000..c8e70ce
--- /dev/null
+++ b/NewFTPServer/FTPServer/Server.cs
@@ -0,0 +1,197 @@
+using System.Diagnostics;
+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;
+
+ ///
+ /// Class constructor
+ ///
+ /// The absolute path of the server location
+ public Server(string locate, int port)
+ {
+ if (locate == null)
+ {
+ throw new ArgumentNullException();
+ }
+ Server.locate = locate;
+ listener = new(IPAddress.Any, port);
+ cancellationToken = new();
+ tasks = new();
+ clients = new();
+ }
+
+ ///
+ /// Starting the server
+ ///
+ public async Task Start()
+ {
+ if (listener == null || clients == null
+ || tasks == null || cancellationToken == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ listener.Start();
+ Console.WriteLine("Server started working");
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ Console.WriteLine("Waiting a client");
+ var client = await listener.AcceptTcpClientAsync(cancellationToken.Token);
+ clients.Add(client);
+ tasks.Add(Listen(client));
+ }
+
+ Task.WaitAll(tasks.ToArray());
+ foreach (var client in clients)
+ {
+ client.Close();
+ }
+
+ tasks.Clear();
+
+ listener.Stop();
+ }
+
+ private static Task Listen(TcpClient client)
+ {
+ if (cancellationToken == null)
+ {
+ Stop();
+ throw new ArgumentNullException(nameof(cancellationToken));
+ }
+
+ return Task.Run(async () =>
+ {
+ if (client == null)
+ {
+ Stop();
+ throw new ArgumentNullException("client");
+ }
+
+ var stream = client.GetStream();
+
+ if (!cancellationToken.IsCancellationRequested)
+ {
+ var reader = new StreamReader(stream, Encoding.UTF8);
+ var stringCommand = await reader.ReadLineAsync();
+
+ if (stringCommand == null)
+ {
+ stream.Close();
+ Stop();
+ throw new InvalidOperationException();
+ }
+
+ if (stringCommand[0] == '1')
+ {
+ List(stringCommand.TrimStart('1', ' '), stream);
+ }
+ else
+ {
+ Get(stringCommand.TrimStart('2', ' '), stream);
+ }
+ }
+ }
+ );
+ }
+
+ ///
+ /// Server shutdown
+ ///
+ public static void Stop()
+ {
+ if (listener != null && cancellationToken != null)
+ {
+ cancellationToken.Cancel();
+ }
+ }
+
+ private static void Get(string directory, NetworkStream stream)
+ {
+ Task.Run(async () =>
+ {
+ if (locate == null)
+ {
+ stream.Close();
+ Stop();
+ throw new NullReferenceException();
+ }
+
+ 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"));
+ }
+ else
+ {
+ var textBytes = File.ReadAllBytes(path);
+ await stream.WriteAsync(Encoding.UTF8.GetBytes($"{textBytes.Length} "));
+ await stream.WriteAsync(textBytes);
+ }
+ stream.Close();
+ });
+ }
+ private static void List(string directory, NetworkStream stream)
+ {
+ Task.Run(async () =>
+ {
+ if (locate == null)
+ {
+ stream.Close();
+ Stop();
+ throw new NullReferenceException();
+ }
+
+ 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\n"));
+ }
+ else
+ {
+ var filesAndDirectories = new StringBuilder();
+ var directories = Directory.GetDirectories(path);
+
+ var sizeFilesAndDirectories = directories.Length;
+
+ foreach (var directory in directories)
+ {
+ filesAndDirectories.Append(" " + directory.Substring(directory.LastIndexOf('\\') + 1) + " true");
+ }
+
+ var files = Directory.GetFiles(path);
+ sizeFilesAndDirectories += files.Length;
+
+ foreach (var file in files)
+ {
+ filesAndDirectories.Append(" " + file.Substring(file.LastIndexOf('\\') + 1) + " false");
+ }
+
+ filesAndDirectories.Append('\n');
+ filesAndDirectories.Insert(0, sizeFilesAndDirectories.ToString());
+
+ await stream.WriteAsync(Encoding.UTF8.GetBytes(filesAndDirectories.ToString()));
+ }
+ stream.Close();
+ });
+ }
+}
\ No newline at end of file
diff --git a/NewFTPServer/NewFTPServer.sln b/NewFTPServer/NewFTPServer.sln
new file mode 100644
index 0000000..d32f6ba
--- /dev/null
+++ b/NewFTPServer/NewFTPServer.sln
@@ -0,0 +1,37 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33403.182
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FTPServer", "FTPServer\FTPServer.csproj", "{D9E2CBBA-EE73-4149-A774-70DC12B4886E}"
+EndProject
+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
+ 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
+ {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
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {39F5B087-17DF-4DAF-9AC5-B12D1F761E54}
+ EndGlobalSection
+EndGlobal
diff --git a/NewFTPServer/TestsFTP/TestsFTP.cs b/NewFTPServer/TestsFTP/TestsFTP.cs
new file mode 100644
index 0000000..f61a7ca
--- /dev/null
+++ b/NewFTPServer/TestsFTP/TestsFTP.cs
@@ -0,0 +1,52 @@
+namespace TestsFTP;
+using SimpleFTP;
+
+public class Tests
+{
+ Server server = new SimpleFTP.Server(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestsFTP"), 7777);
+ Client client = new Client(7777, "localhost");
+
+ [SetUp]
+ public void SetUp()
+ {
+ if (server == null)
+ {
+ return;
+ }
+ Task.Run(() => server.Start());
+ }
+
+ [Test]
+ public void GettingInformationFromANonExistentFile()
+ {
+ var result = client.Get("./test.txt");
+ Assert.That(result.Result, Is.EqualTo("-1"));
+ }
+
+ [Test]
+ public void GettingInformationFromExistentFile()
+ {
+ var result = client.Get("./testForGet.txt");
+ Assert.That(result.Result, Is.EqualTo("3 123"));
+ }
+
+ [Test]
+ public void GettingInformationFromNonExistentDirectory()
+ {
+ var result = client.List("./testForLister");
+ Assert.That(result.Result, Is.EqualTo("-1"));
+ }
+
+ [Test]
+ public void GettingInformationFromExistentDirectory()
+ {
+ var result = client.List("./testForList");
+ Assert.That(result.Result, Is.EqualTo("3 test3 true test1.txt false test2.txt false"));
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ server.Stop();
+ }
+}
\ 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
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