diff --git a/WebChat/WebChat.sln b/WebChat/WebChat.sln
new file mode 100644
index 0000000..3db5de5
--- /dev/null
+++ b/WebChat/WebChat.sln
@@ -0,0 +1,16 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebChat", "WebChat\WebChat.csproj", "{26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/WebChat/WebChat/Client.cs b/WebChat/WebChat/Client.cs
new file mode 100644
index 0000000..5a093b4
--- /dev/null
+++ b/WebChat/WebChat/Client.cs
@@ -0,0 +1,53 @@
+namespace WebChat;
+
+using System.Net.Sockets;
+
+///
+/// Chat client.
+///
+public class Client : IDisposable
+{
+ private readonly TcpClient _client;
+
+ private readonly NetworkStream _networkStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Client(string host, int port)
+ {
+ _client = new TcpClient(host, port);
+
+ _networkStream = _client.GetStream();
+ }
+
+ ///
+ /// Gets a value indicating whether the client is disposed.
+ ///
+ public bool IsDisposed { get; private set; }
+
+ ///
+ /// Releases all resources used by the current instance of the class.
+ ///
+ public void Dispose()
+ {
+ if (IsDisposed)
+ {
+ return;
+ }
+
+ _networkStream.Dispose();
+ _client.Dispose();
+
+ IsDisposed = true;
+ }
+
+ ///
+ /// Runs client.
+ ///
+ public async Task RunAsync()
+ {
+ await Processing.ProcessQuery(_networkStream);
+ }
+
+}
diff --git a/WebChat/WebChat/Processing.cs b/WebChat/WebChat/Processing.cs
new file mode 100644
index 0000000..90056cb
--- /dev/null
+++ b/WebChat/WebChat/Processing.cs
@@ -0,0 +1,45 @@
+namespace WebChat;
+
+using System.Net.Sockets;
+
+///
+/// Class for processing get and post queries.
+///
+public static class Processing
+{
+ ///
+ /// Processes get and post queries.
+ ///
+ /// Working stream.
+ public static async Task ProcessQuery(NetworkStream stream)
+ {
+ await Task.Run(async () => await Post(stream));
+ await Task.Run(async () => await Get(stream));
+ }
+
+ private static async Task Post(NetworkStream stream)
+ {
+ while (true)
+ {
+ var writer = new StreamWriter(stream);
+ var message = Console.ReadLine();
+ await writer.WriteAsync(message);
+ await writer.FlushAsync();
+ await stream.FlushAsync();
+
+ writer = null;
+ }
+ }
+
+ private static async Task Get(NetworkStream stream)
+ {
+ while (true)
+ {
+ var reader = new StreamReader(stream);
+ var message = await reader.ReadLineAsync();
+ Console.WriteLine(message);
+
+ reader = null;
+ }
+ }
+}
diff --git a/WebChat/WebChat/Program.cs b/WebChat/WebChat/Program.cs
new file mode 100644
index 0000000..6112162
--- /dev/null
+++ b/WebChat/WebChat/Program.cs
@@ -0,0 +1,43 @@
+using WebChat;
+
+switch (args.Length)
+{
+ case 1:
+ {
+ await StartServer(args);
+ break;
+ }
+
+ case 2:
+ {
+ await StartClient(args);
+ break;
+ }
+
+ default:
+ {
+ throw new ArgumentException();
+ }
+}
+
+async Task StartClient(string[] args)
+{
+ if (!int.TryParse(args[1], out var port))
+ {
+ throw new ArgumentException();
+ }
+
+ using var client = new Client(args[0], port);
+ await client.RunAsync();
+}
+
+async Task StartServer(string[] args)
+{
+ if (!int.TryParse(args[0], out var port))
+ {
+ throw new ArgumentException();
+ }
+
+ using var server = new Server(port);
+ await server.RunAsync();
+}
\ No newline at end of file
diff --git a/WebChat/WebChat/Server.cs b/WebChat/WebChat/Server.cs
new file mode 100644
index 0000000..1c0611c
--- /dev/null
+++ b/WebChat/WebChat/Server.cs
@@ -0,0 +1,68 @@
+namespace WebChat;
+
+using System.Net;
+using System.Net.Sockets;
+
+///
+/// Chat server.
+///
+public class Server : IDisposable
+{
+ private readonly TcpListener _listener;
+
+ private readonly CancellationTokenSource _cts = new ();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Server(int port)
+ {
+ _listener = new TcpListener(IPAddress.Any, port);
+ }
+
+ ///
+ /// Gets a value indicating whether the server is disposed.
+ ///
+ public bool IsDisposed { get; private set; }
+
+ private void Stop() => _cts.Cancel();
+
+ ///
+ /// Releases all resources used by the current instance of the class.
+ ///
+ public void Dispose()
+ {
+ if (IsDisposed)
+ {
+ return;
+ }
+
+ if (!_cts.IsCancellationRequested)
+ {
+ Stop();
+ }
+
+ _cts.Dispose();
+ IsDisposed = true;
+ }
+
+ ///
+ /// Runs server.
+ ///
+ public async Task RunAsync()
+ {
+ _listener.Start();
+
+ try
+ {
+ var token = _cts.Token;
+ using var socket = await _listener.AcceptSocketAsync(token);
+ await using var stream = new NetworkStream(socket);
+ await Processing.ProcessQuery(stream);
+ }
+ finally
+ {
+ _listener.Stop();
+ }
+ }
+}
diff --git a/WebChat/WebChat/WebChat.csproj b/WebChat/WebChat/WebChat.csproj
new file mode 100644
index 0000000..b9de063
--- /dev/null
+++ b/WebChat/WebChat/WebChat.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+