C# .Net рдлреНрд░реЗрдорд╡рд░реНрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдкреНрд░рдЧрдд рд╕рд╛рдпрдХрд▓рд┐рдВрдЧ рдХрд┐рдВрд╡рд╛ рдХреНрд▓рд╛рдпрдВрдЯ-рд╕рд░реНрд╡реНрд╣рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ

рдиреЛрдВрдж

рдЬреЗрд╡реНрд╣рд╛ рдПрдХрд╛ рд╕рд╣рдХрд╛рд▒реНрдпрд╛рдиреЗ рдорд▓рд╛ рдПрдХ рдЫреЛрдЯреА рд╡реЗрдм рд╕реЗрд╡рд╛ рдмрдирд╡рдгреНрдпрд╛рдЪреА рд╕реВрдЪрдирд╛ рдХреЗрд▓реА рддреЗрд╡реНрд╣рд╛ рд╣реЗ рд╕рд░реНрд╡ рд╕реБрд░реВ рдЭрд╛рд▓реЗ. рд╣реЗ рдЯрд┐рдВрдбрд░рд╕рд╛рд░рдЦреЗ рдХрд╛рд╣реАрддрд░реА рдЕрд╕рд╛рд╡реЗ, рдкрд░рдВрддреБ рдЖрдпрдЯреА рд╣рдБрдЧрдЖрдЙрдЯрд╕рд╛рдареА. рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЕрдЧрджреА рд╕реЛрдкреА рдЖрд╣реЗ, рддреБрдореНрд╣реА рдиреЛрдВрджрдгреА рдХрд░рд╛, рдкреНрд░реЛрдлрд╛рдЗрд▓ рднрд░рд╛ рдЖрдгрд┐ рдореБрдЦреНрдп рдореБрджреНрджреНрдпрд╛рдХрдбреЗ рдЬрд╛, рдореНрд╣рдгрдЬреЗ рдПрдХ рд╕рдВрд╡рд╛рджрдХ рд╢реЛрдзрдгреЗ рдЖрдгрд┐ рддреБрдордЪреЗ рдХрдиреЗрдХреНрд╢рди рд╡рд╛рдврд╡рдгреЗ рдЖрдгрд┐ рдирд╡реАрди рдУрд│рдЦреА рдХрд░рдгреЗ.

рдпреЗрдереЗ рдорд▓рд╛ рдорд╛рдЭреНрдпрд╛рдмрджреНрджрд▓ рдереЛрдбреЗ рд╡рд┐рд╖рдпрд╛рдВрддрд░ рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓, рдЬреЗрдгреЗрдХрд░реВрди рднрд╡рд┐рд╖реНрдпрд╛рдд рдореА рд╡рд┐рдХрд╛рд╕рд╛рдд рдЕрд╢реА рдкрд╛рд╡рд▓реЗ рдХрд╛ рдЙрдЪрд▓рд▓реА рд╣реЗ рд╕реНрдкрд╖реНрдЯ рд╣реЛрдИрд▓.

рдпрд╛ рдХреНрд╖рдгреА рдореА рдПрдХрд╛ рдЧреЗрдо рд╕реНрдЯреБрдбрд┐рдУрдордзреНрдпреЗ рддрд╛рдВрддреНрд░рд┐рдХ рдХрд▓рд╛рдХрд╛рд░рд╛рдЪреЗ рд╕реНрдерд╛рди рдзрд╛рд░рдг рдХрд░рддреЛ, рдорд╛рдЭрд╛ C# рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдЕрдиреБрднрд╡ рдлрдХреНрдд рдпреБрдирд┐рдЯреАрд╕рд╛рдареА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЖрдгрд┐ рдЙрдкрдпреБрдХреНрддрддрд╛ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд рд╣реЛрддрд╛ рдЖрдгрд┐ рдпрд╛ рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, Android рдбрд┐рд╡реНрд╣рд╛рдЗрд╕реЗрд╕рд╕рд╣ рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рдХрд╛рдорд╛рд╕рд╛рдареА рдкреНрд▓рдЧрдЗрди рддрдпрд╛рд░ рдХрд░рдгреЗ. рдпрд╛ рдЬрдЧрд╛рдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░, рдореА рдЕрджреНрдпрд╛рдк рдирд┐рд╡рдбрд▓реЗрд▓реА рдирд╛рд╣реА рдЖрдгрд┐ рдирдВрддрд░ рдЕрд╢реА рд╕рдВрдзреА рдЪрд╛рд▓реВ рдХреЗрд▓реА.

рднрд╛рдЧ 1. рдлреНрд░реЗрдо рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдкрд┐рдВрдЧ

рд╣реА рд╕реЗрд╡рд╛ рдХрд╢реА рдЕрд╕реЗрд▓ рд╣реЗ рдард░рд╡реВрди, рдореА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрд╕рд╛рдареА рдкрд░реНрдпрд╛рдп рд╢реЛрдзреВ рд▓рд╛рдЧрд▓реЛ. рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкрд╛ рдорд╛рд░реНрдЧ рдореНрд╣рдгрдЬреЗ рдХрд╛рд╣реА рдкреНрд░рдХрд╛рд░рдЪреЗ рд░реЗрдбреАрдореЗрдб рд╕реЛрд▓реНрдпреВрд╢рди рд╢реЛрдзрдгреЗ, рдЬреНрдпрд╛рд╡рд░ рдЖрдкрдг рдЬрдЧрд╛рд╡рд░реАрд▓ рдШреБрдмрдбрд╛рд╕рд╛рд░рдЦреЗ, рдЖрдордЪреЗ рдпрд╛рдВрддреНрд░рд┐рдХреА рдЦреЗрдЪреВ рд╢рдХрддрд╛ рдЖрдгрд┐ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдирд┐рдВрджрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╕рдВрдкреВрд░реНрдг рдЧреЛрд╖реНрдЯ рдорд╛рдВрдбреВ рд╢рдХрддрд╛.
рдкрд░рдВрддреБ рд╣реЗ рдордиреЛрд░рдВрдЬрдХ рдирд╛рд╣реА, рдорд▓рд╛ рдпрд╛рдд рдХреЛрдгрддреЗрд╣реА рдЖрд╡реНрд╣рд╛рди рдЖрдгрд┐ рдЕрд░реНрде рджрд┐рд╕рд▓рд╛ рдирд╛рд╣реА рдЖрдгрд┐ рдореНрд╣рдгреВрди рдореА рд╡реЗрдм рддрдВрддреНрд░рдЬреНрдЮрд╛рди рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╢реА рд╕рдВрд╡рд╛рдж рд╕рд╛рдзрдгреНрдпрд╛рдЪреНрдпрд╛ рдкрджреНрдзрддреАрдВрдЪрд╛ рдЕрднреНрдпрд╛рд╕ рдХрд░рдгреНрдпрд╛рд╕ рд╕реБрд░рд╡рд╛рдд рдХреЗрд▓реА.

C# .Net рд╡рд░реАрд▓ рд▓реЗрдЦ рдЖрдгрд┐ рдХрд╛рдЧрджрдкрддреНрд░реЗ рдкрд╛рд╣реВрди рдЕрднреНрдпрд╛рд╕рд╛рд▓рд╛ рд╕реБрд░реБрд╡рд╛рдд рдЭрд╛рд▓реА. рдпреЗрдереЗ рдорд▓рд╛ рдХрд╛рд░реНрдп рдкреВрд░реНрдг рдХрд░рдгреНрдпрд╛рдЪреЗ рд╡рд┐рд╡рд┐рдз рдорд╛рд░реНрдЧ рд╕рд╛рдкрдбрд▓реЗ. рдиреЗрдЯрд╡рд░реНрдХрд╢реА рд╕рдВрд╡рд╛рдж рд╕рд╛рдзрдгреНрдпрд╛рд╕рд╛рдареА ASP.Net рдХрд┐рдВрд╡рд╛ Azure рд╕реЗрд╡рд╛рдВрд╕рд╛рд░рдЦреНрдпрд╛ рдкреВрд░реНрдг рд╕рдорд╛рдзрд╛рдирд╛рдкрд╛рд╕реВрди, TcpHttp рдХрдиреЗрдХреНрд╢рдирд╢реА рдереЗрдЯ рд╕рдВрд╡рд╛рдж рд╕рд╛рдзрдгреНрдпрд╛рд╕рд╛рдареА рдЕрдиреЗрдХ рдпрдВрддреНрд░рдгрд╛ рдЖрд╣реЗрдд.

рдПрдПрд╕рдкреАрд╕рд╣ рдкрд╣рд┐рд▓рд╛ рдкреНрд░рдпрддреНрди рдХреЗрд▓реНрдпрд╛рд╡рд░, рдореА рддрд╛рдмрдбрддреЛрдм рддреЛ рд░рджреНрдж рдХреЗрд▓рд╛, рдорд╛рдЭреНрдпрд╛ рдорддреЗ рдЖрдордЪреНрдпрд╛ рд╕реЗрд╡реЗрд╕рд╛рдареА рдирд┐рд░реНрдгрдп рдШреЗрдгреЗ рдЦреВрдк рдХрдареАрдг рд╣реЛрддреЗ. рдЖрдореНрд╣реА рдпрд╛ рдкреНрд▓реЕрдЯрдлреЙрд░реНрдордЪреНрдпрд╛ рдХреНрд╖рдорддреЗрдкреИрдХреА рдПрдХ рддреГрддреАрдпрд╛рдВрд╢ рджреЗрдЦреАрд▓ рд╡рд╛рдкрд░рдгрд╛рд░ рдирд╛рд╣реА, рдореНрд╣рдгреВрди рдореА рдорд╛рдЭрд╛ рд╢реЛрдз рд╕реБрд░реВ рдареЗрд╡рд▓рд╛. рдирд┐рд╡рдб TCP рдЖрдгрд┐ Http рдХреНрд▓рд╛рдпрдВрдЯ-рд╕рд░реНрд╡реНрд╣рд░ рджрд░рдореНрдпрд╛рди рдЙрджреНрднрд╡рд▓реА. рдпреЗрдереЗ, Habr├й рд╡рд░, рдорд▓рд╛ рдпрд╛рдмрджреНрджрд▓ рдПрдХ рд▓реЗрдЦ рдЖрд▓рд╛ рдорд▓реНрдЯреАрдереНрд░реЗрдбреЗрдб рд╕рд░реНрд╡реНрд╣рд░, рд╕рдВрдХрд▓рд┐рдд рдЖрдгрд┐ рдЪрд╛рдЪрдгреА рдХреЗрд▓реНрдпрд╛рд╡рд░, рдореА TCP рдХрдиреЗрдХреНрд╢рдирд╢реА рд╕рдВрд╡рд╛рдж рд╕рд╛рдзрдгреНрдпрд╛рд╡рд░ рд▓рдХреНрд╖ рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддрд▓рд╛, рдХрд╛рд╣реА рдХрд╛рд░рдгрд╛рд╕реНрддрд╡ рдорд▓рд╛ рд╡рд╛рдЯрд▓реЗ рдХреА http рдорд▓рд╛ рдХреНрд░реЙрд╕-рдкреНрд▓реЕрдЯрдлреЙрд░реНрдо рд╕реЛрд▓реНрдпреВрд╢рди рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрдгрд╛рд░ рдирд╛рд╣реА.

рд╕рд░реНрд╡реНрд╣рд░рдЪреНрдпрд╛ рдкрд╣рд┐рд▓реНрдпрд╛ рдЖрд╡реГрддреНрддреАрдордзреНрдпреЗ рдХрдиреЗрдХреНрд╢рди рд╣рд╛рддрд╛рд│рдгреЗ, рд╕реНрдерд┐рд░ рд╡реЗрдм рдкреГрд╖реНрда рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд╛рди рдХрд░рдгреЗ рдЖрдгрд┐ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдХрд░рдгреЗ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдЖрд╣реЗ. рдЖрдгрд┐ рд╕реБрд░реБрд╡рд╛рддреАрдЪреНрдпрд╛рд╕рд╛рдареА, рдореА рд╕рд╛рдЗрдЯрд╡рд░ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдПрдХ рдлрдВрдХреНрд╢рдирд▓ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддрд▓рд╛, рдЬреЗрдгреЗрдХрд░реВрди рдирдВрддрд░ рдореА рдпреЗрдереЗ android рдЖрдгрд┐ ios рд╡рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдмрд╛рдВрдзреВ рд╢рдХреЗрди.

рдпреЗрдереЗ рдХрд╛рд╣реА рдХреЛрдб рдЖрд╣реЗ
рдЕрдВрддрд╣реАрди рд▓реВрдкрдордзреНрдпреЗ рдЧреНрд░рд╛рд╣рдХрд╛рдВрдирд╛ рд╕реНрд╡реАрдХрд╛рд░рдгрд╛рд░рд╛ рдореБрдЦреНрдп рдзрд╛рдЧрд╛:

using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace ClearServer
{

    class Server
    {
        TcpListener Listener;
        public Server(int Port)
        {
            Listener = new TcpListener(IPAddress.Any, Port);
            Listener.Start();

            while (true)
            {
                TcpClient Client = Listener.AcceptTcpClient();
                Thread Thread = new Thread(new ParameterizedThreadStart(ClientThread));
                Thread.Start(Client);
            }
        }

        static void ClientThread(Object StateInfo)
        {
            new Client((TcpClient)StateInfo);
        }

        ~Server()
        {
            if (Listener != null)
            {
                Listener.Stop();
            }
        }

        static void Main(string[] args)
        {
            DatabaseWorker sqlBase = DatabaseWorker.GetInstance;

            new Server(80);
        }
    }
}

рдХреНрд▓рд╛рдпрдВрдЯ рд╣рдБрдбрд▓рд░ рд╕реНрд╡рддрдГ:

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace ClearServer
{
    class Client
    {


        public Client(TcpClient Client)
        {

            string Message = "";
            byte[] Buffer = new byte[1024];
            int Count;
            while ((Count = Client.GetStream().Read(Buffer, 0, Buffer.Length)) > 0)
            {
                Message += Encoding.UTF8.GetString(Buffer, 0, Count);

                if (Message.IndexOf("rnrn") >= 0 || Message.Length > 4096)
                {
                    Console.WriteLine(Message);
                    break;
                }
            }

            Match ReqMatch = Regex.Match(Message, @"^w+s+([^s?]+)[^s]*s+HTTP/.*|");
            if (ReqMatch == Match.Empty)
            {
                ErrorWorker.SendError(Client, 400);
                return;
            }
            string RequestUri = ReqMatch.Groups[1].Value;
            RequestUri = Uri.UnescapeDataString(RequestUri);
            if (RequestUri.IndexOf("..") >= 0)
            {
                ErrorWorker.SendError(Client, 400);
                return;
            }
            if (RequestUri.EndsWith("/"))
            {
                RequestUri += "index.html";
            }

            string FilePath =

quot;D:/Web/TestSite{RequestUri}";

if (!File.Exists(FilePath))
{
ErrorWorker.SendError(Client, 404);
return;
}

string Extension = RequestUri.Substring(RequestUri.LastIndexOf('.'));

string ContentType = "";

switch (Extension)
{
case ".htm":
case ".html":
ContentType = "text/html";
break;
case ".css":
ContentType = "text/css";
break;
case ".js":
ContentType = "text/javascript";
break;
case ".jpg":
ContentType = "image/jpeg";
break;
case ".jpeg":
case ".png":
case ".gif":
ContentType =


quot;image/{Extension.Substring(1)}";
break;
default:
if (Extension.Length > 1)
{
ContentType =


quot;application/{Extension.Substring(1)}";
}
else
{
ContentType = "application/unknown";
}
break;
}

FileStream FS;
try
{
FS = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
catch (Exception)
{
ErrorWorker.SendError(Client, 500);
return;
}

string Headers =


quot;HTTP/1.1 200 OKnContent-Type: {ContentType}nContent-Length: {FS.Length}nn";
byte[] HeadersBuffer = Encoding.ASCII.GetBytes(Headers);
Client.GetStream().Write(HeadersBuffer, 0, HeadersBuffer.Length);

while (FS.Position < FS.Length)
{
Count = FS.Read(Buffer, 0, Buffer.Length);
Client.GetStream().Write(Buffer, 0, Count);
}

FS.Close();
Client.Close();
}
}
}

рдЖрдгрд┐ рд╕реНрдерд╛рдирд┐рдХ SQL рд╡рд░ рддрдпрд╛рд░ рдХреЗрд▓реЗрд▓рд╛ рдкрд╣рд┐рд▓рд╛ рдбреЗрдЯрд╛рдмреЗрд╕:

using System;
using System.Data.Linq;
namespace ClearServer
{
    class DatabaseWorker
    {

        private static DatabaseWorker instance;

        public static DatabaseWorker GetInstance
        {
            get
            {
                if (instance == null)
                    instance = new DatabaseWorker();
                return instance;
            }
        }


        private DatabaseWorker()
        {
            string connectionStr = databasePath;
            using (DataContext db = new DataContext(connectionStr))
            {
                Table<User> users = db.GetTable<User>();
                foreach (var item in users)
                {
                    Console.WriteLine(

quot;{item.login} {item.password}");
}
}
}
}
}

рдЬрд╕реЗ рдЖрдкрдг рдкрд╛рд╣реВ рд╢рдХрддрд╛, рд╣реА рдЖрд╡реГрддреНрддреА рд▓реЗрдЦрд╛рддреАрд▓ рдЖрд╡реГрддреНрддреАрдкреЗрдХреНрд╖рд╛ рдереЛрдбреА рд╡реЗрдЧрд│реА рдЖрд╣реЗ. рдЦрд░рдВ рддрд░, рд╕рдВрдЧрдгрдХрд╛рд╡рд░реАрд▓ рдлреЛрд▓реНрдбрд░рдордзреВрди рдлрдХреНрдд рдкреГрд╖реНрдареЗ рд▓реЛрдб рдХрд░рдгреЗ рдЖрдгрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдпреЗрдереЗ рдЬреЛрдбрд▓реЗ рдЧреЗрд▓реЗ (рдЬреЗ, рдЪреБрдХреАрдЪреНрдпрд╛ рдХрдиреЗрдХреНрд╢рди рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░рдореБрд│реЗ, рдпрд╛ рдЖрд╡реГрддреНрддреАрдордзреНрдпреЗ рдХрд╛рд░реНрдп рдХрд░рдд рдирд╛рд╣реА).

рдзрдбрд╛ 2

рд╕рд░реНрд╡реНрд╣рд░рдЪреА рдЪрд╛рдЪрдгреА рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рдореА рдирд┐рд╖реНрдХрд░реНрд╖рд╛рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪрд▓реЛ рдХреА рд╣рд╛ рдПрдХ рдЪрд╛рдВрдЧрд▓рд╛ рдЙрдкрд╛рдп рдЕрд╕реЗрд▓ (рдмрд┐рдШрдбрд╡рдгрд╛рд░рд╛: рдирд╛рд╣реА), рдЖрдордЪреНрдпрд╛ рд╕реЗрд╡реЗрд╕рд╛рдареА, рдореНрд╣рдгреВрди рдкреНрд░рдХрд▓реНрдкрд╛рдиреЗ рддрд░реНрдХ рдШреЗрдгреНрдпрд╛рд╕ рд╕реБрд░реБрд╡рд╛рдд рдХреЗрд▓реА.
рдЯрдкреНрдкреНрдпрд╛рдЯрдкреНрдкреНрдпрд╛рдиреЗ, рдирд╡реАрди рдореЙрдбреНрдпреВрд▓ рджрд┐рд╕реВ рд▓рд╛рдЧрд▓реЗ рдЖрдгрд┐ рд╕рд░реНрд╡реНрд╣рд░рдЪреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╡рд╛рдврд▓реА. рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рдЪрд╛рдЪрдгреА рдбреЛрдореЗрди рдЖрдгрд┐ ssl рдХрдиреЗрдХреНрд╢рди рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдорд┐рд│рд╛рд▓реЗ рдЖрд╣реЗ.

рд╕рд░реНрд╡реНрд╣рд░рдЪреЗ рддрд░реНрдХрд╢рд╛рд╕реНрддреНрд░ рдЖрдгрд┐ рдХреНрд▓рд╛рдпрдВрдЯрдЪреНрдпрд╛ рдкреНрд░рдХреНрд░рд┐рдпреЗрдЪреЗ рд╡рд░реНрдгрди рдХрд░рдгрд╛рд░рд╛ рдЖрдгрдЦреА рдереЛрдбрд╛ рдХреЛрдб
рдкреНрд░рдорд╛рдгрдкрддреНрд░рд╛рдЪреНрдпрд╛ рд╡рд╛рдкрд░рд╛рд╕рд╣ рд╕рд░реНрд╡реНрд╣рд░рдЪреА рдЕрджреНрдпрдпрд╛рд╡рдд рдЖрд╡реГрддреНрддреА.

using System;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Security.Policy;
using System.Threading;


namespace ClearServer
{

    sealed class Server
    {
        readonly bool ServerRunning = true;
        readonly TcpListener sslListner;
        public static X509Certificate serverCertificate = null;
        Server()
        {
            serverCertificate = X509Certificate.CreateFromSignedFile(@"C:sslitinder.online.crt");
            sslListner = new TcpListener(IPAddress.Any, 443);
            sslListner.Start();
            Console.WriteLine("Starting server.." + serverCertificate.Subject + "n" + Assembly.GetExecutingAssembly().Location);
            while (ServerRunning)
            {
                TcpClient SslClient = sslListner.AcceptTcpClient();
                Thread SslThread = new Thread(new ParameterizedThreadStart(ClientThread));
                SslThread.Start(SslClient);
            }
            
        }
        static void ClientThread(Object StateInfo)
        {
            new Client((TcpClient)StateInfo);
        }

        ~Server()
        {
            if (sslListner != null)
            {
                sslListner.Stop();
            }
        }

        public static void Main(string[] args)
        {
            if (AppDomain.CurrentDomain.IsDefaultAppDomain())
            {
                Console.WriteLine("Switching another domain");
                new AppDomainSetup
                {
                    ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase
                };
                var current = AppDomain.CurrentDomain;
                var strongNames = new StrongName[0];
                var domain = AppDomain.CreateDomain(
                    "ClearServer", null,
                    current.SetupInformation, new PermissionSet(PermissionState.Unrestricted),
                    strongNames);
                domain.ExecuteAssembly(Assembly.GetExecutingAssembly().Location);
            }
            new Server();
        }
    }
}

рддрд╕реЗрдЪ ssl рджреНрд╡рд╛рд░реЗ рдЕрдзрд┐рдХреГрддрддреЗрд╕рд╣ рдирд╡реАрди рдХреНрд▓рд╛рдпрдВрдЯ рд╣рдБрдбрд▓рд░:

using ClearServer.Core.Requester;
using System;
using System.Net.Security;
using System.Net.Sockets;

namespace ClearServer
{
    public class Client
    {
        public Client(TcpClient Client)
        {
            SslStream SSlClientStream = new SslStream(Client.GetStream(), false);
            try
            {
                SSlClientStream.AuthenticateAsServer(Server.serverCertificate, clientCertificateRequired: false, checkCertificateRevocation: true);
            }
            catch (Exception e)
            {
                Console.WriteLine(
                    "---------------------------------------------------------------------n" +


quot;|{DateTime.Now:g}n|------------n|{Client.Client.RemoteEndPoint}n|------------n|Exception: {e.Message}n|------------n|Authentication failed - closing the connection.n" +
"---------------------------------------------------------------------n");
SSlClientStream.Close();
Client.Close();
}
new RequestContext(SSlClientStream, Client);
}

}
}

рдкрд░рдВрддреБ рд╕рд░реНрд╡реНрд╣рд░ рдХреЗрд╡рд│ TCP рдХрдиреЗрдХреНрд╢рдирд╡рд░ рдХрд╛рд░реНрдп рдХрд░рдд рдЕрд╕рд▓реНрдпрд╛рдиреЗ, рд╡рд┐рдирдВрддреА рд╕рдВрджрд░реНрдн рдУрд│рдЦреВ рд╢рдХреЗрд▓ рдЕрд╕реЗ рдореЙрдбреНрдпреВрд▓ рддрдпрд╛рд░ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдореА рдард░рд╡рд▓реЗ рдЖрд╣реЗ рдХреА рдпреЗрдереЗ рдПрдХ рдкрд╛рд░реНрд╕рд░ рдпреЛрдЧреНрдп рдЖрд╣реЗ рдЬреЛ рдХреНрд▓рд╛рдпрдВрдЯрдЪреНрдпрд╛ рд╡рд┐рдирдВрддреАрд▓рд╛ рд╡реЗрдЧрд│реНрдпрд╛ рднрд╛рдЧрд╛рдВрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрд▓ рдЬреНрдпрд╛рдЪреНрдпрд╛рд╢реА рдореА рдХреНрд▓рд╛рдпрдВрдЯрд▓рд╛ рдЖрд╡рд╢реНрдпрдХ рдЙрддреНрддрд░реЗ рджреЗрдгреНрдпрд╛рд╕рд╛рдареА рд╕рдВрд╡рд╛рдж рд╕рд╛рдзреВ рд╢рдХрддреЛ.

рдкрд╛рд░реНрд╕рд░

using ClearServer.Core.UserController;
using ReServer.Core.Classes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace ClearServer.Core.Requester
{
    public class RequestContext
    {
        public string Message = "";
        private readonly byte[] buffer = new byte[1024];
        public string RequestMethod;
        public string RequestUrl;
        public User RequestProfile;
        public User CurrentUser = null;
        public List<RequestValues> HeadersValues;
        public List<RequestValues> FormValues;
        private TcpClient TcpClient;

        private event Action<SslStream, RequestContext> OnRead = RequestHandler.OnHandle;

        DatabaseWorker databaseWorker = new DatabaseWorker();

        public RequestContext(SslStream ClientStream, TcpClient Client)
        {

            this.TcpClient = Client;
            try
            {
                ClientStream.BeginRead(buffer, 0, buffer.Length, ClientRead, ClientStream);
            }
            catch { return; }
        }
        private void ClientRead(IAsyncResult ar)
        {
            SslStream ClientStream = (SslStream)ar.AsyncState;

            if (ar.IsCompleted)
            {
                Message = Encoding.UTF8.GetString(buffer);
                Message = Uri.UnescapeDataString(Message);
                Console.WriteLine(

quot;n{DateTime.Now:g} Client IP:{TcpClient.Client.RemoteEndPoint}n{Message}");
RequestParse();
HeadersValues = HeaderValues();
FormValues = ContentValues();
UserParse();
ProfileParse();
OnRead?.Invoke(ClientStream, this);
}
}

private void RequestParse()
{
Match methodParse = Regex.Match(Message, @"(^w+)s+([^s?]+)[^s]*s+HTTP/.*|");
RequestMethod = methodParse.Groups[1].Value.Trim();
RequestUrl = methodParse.Groups[2].Value.Trim();
}
private void UserParse()
{
string cookie;
try
{
if (HeadersValues.Any(x => x.Name.Contains("Cookie")))
{
cookie = HeadersValues.FirstOrDefault(x => x.Name.Contains("Cookie")).Value;
try
{
CurrentUser = databaseWorker.CookieValidate(cookie);
}
catch { }
}
}
catch { }

}
private List<RequestValues> HeaderValues()
{
var values = new List<RequestValues>();
var parse = Regex.Matches(Message, @"(.*?): (.*?)n");
foreach (Match match in parse)
{
values.Add(new RequestValues()
{
Name = match.Groups[1].Value.Trim(),
Value = match.Groups[2].Value.Trim()
});
}
return values;
}

private void ProfileParse()
{
if (RequestUrl.Contains("@"))
{
RequestProfile = databaseWorker.FindUser(RequestUrl.Substring(2));
RequestUrl = "/profile";
}
}
private List<RequestValues> ContentValues()
{
var values = new List<RequestValues>();
var output = Message.Trim('n').Split().Last();
var parse = Regex.Matches(output, @"([^&].*?)=([^&]*b)");
foreach (Match match in parse)
{
values.Add(new RequestValues()
{
Name = match.Groups[1].Value.Trim(),
Value = match.Groups[2].Value.Trim().Replace('+', ' ')
});
}
return values;
}
}
}

рддреНрдпрд╛рдЪреЗ рд╕рд╛рд░ рдпрд╛ рд╡рд╕реНрддреБрд╕реНрдерд┐рддреАрдд рдЖрд╣реЗ рдХреА рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддреАрдВрдЪреНрдпрд╛ рдорджрддреАрдиреЗ рд╡рд┐рдирдВрддреАрд▓рд╛ рднрд╛рдЧрд╛рдВрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдгреЗ. рдЖрдореНрд╣рд╛рд▓рд╛ рдХреНрд▓рд╛рдпрдВрдЯрдХрдбреВрди рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддреЛ, рдкрд╣рд┐рд▓реА рдУрд│ рдирд┐рд╡рдбрд╛, рдЬреНрдпрд╛рдордзреНрдпреЗ рдкрджреНрдзрдд рдЖрдгрд┐ рд╡рд┐рдирдВрддреА url рдЖрд╣реЗ. рдордЧ рдЖрдкрдг рд╣реЗрдбрд░ рд╡рд╛рдЪрддреЛ, рдЬреЗ рдЖрдкрдг HeaderName = Content рдпрд╛ рдлреЙрд░реНрдордЪреНрдпрд╛ рдЕреЕрд░реЗрдордзреНрдпреЗ рдЪрд╛рд▓рд╡рддреЛ рдЖрдгрд┐ рд╕реЛрдмрддрдЪрд╛ рдордЬрдХреВрд░ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, querystring) рджреЗрдЦреАрд▓ рд╢реЛрдзрддреЛ, рдЬреНрдпрд╛рд▓рд╛ рдЖрдкрдг рд╕рдорд╛рди рдЕреЕрд░реЗрдордзреНрдпреЗ рджреЗрдЦреАрд▓ рдЪрд╛рд▓рд╡рд┐рддреЛ. рдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рд╡рд░реНрддрдорд╛рди рдХреНрд▓рд╛рдпрдВрдЯ рдЕрдзрд┐рдХреГрдд рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рд╣реЗ рдкрд╛рд░реНрд╕рд░ рд╢реЛрдзрддреЛ рдЖрдгрд┐ рддреНрдпрд╛рдЪрд╛ рдбреЗрдЯрд╛ рдЬрддрди рдХрд░рддреЛ. рдЕрдзрд┐рдХреГрдд рдХреНрд▓рд╛рдпрдВрдЯрдЪреНрдпрд╛ рд╕рд░реНрд╡ рд╡рд┐рдирдВрддреНрдпрд╛рдВрдордзреНрдпреЗ рдЕрдзрд┐рдХреГрддрддрд╛ рд╣реЕрд╢ рдЕрд╕рддреЛ, рдЬреЛ рдХреБрдХреАрдЬрдордзреНрдпреЗ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХреЗрд▓рд╛ рдЬрд╛рддреЛ, рдЬреНрдпрд╛рдореБрд│реЗ рджреЛрди рдкреНрд░рдХрд╛рд░рдЪреНрдпрд╛ рдХреНрд▓рд╛рдпрдВрдЯрд╕рд╛рдареА рдкреБрдвреАрд▓ рдХрд╛рд░реНрдп рддрд░реНрдХ рд╡реЗрдЧрд│реЗ рдХрд░рдгреЗ рдЖрдгрд┐ рддреНрдпрд╛рдВрдирд╛ рдпреЛрдЧреНрдп рдЙрддреНрддрд░реЗ рджреЗрдгреЗ рд╢рдХреНрдп рд╣реЛрддреЗ.

рдмрд░рдВ, "site.com/@UserName" рд╕рд╛рд░рдЦреНрдпрд╛ рд╡рд┐рдирдВрддреНрдпрд╛ рдбрд╛рдпрдиреЕрдорд┐рдХрд▓реА рд╡реНрдпреБрддреНрдкрдиреНрди рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдкреГрд╖реНрдард╛рдВрдордзреНрдпреЗ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░реВрди, рдПрдХ рд▓рд╣рд╛рди, рдЫрд╛рди рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рдЬреЗ рд╡реЗрдЧрд│реНрдпрд╛ рдореЙрдбреНрдпреВрд▓рдордзреНрдпреЗ рд╣рд▓рд╡рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ. рд╡рд┐рдирдВрддреАрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рдЦрд╛рд▓реАрд▓ рдореЙрдбреНрдпреВрд▓ рдкреНрд▓реЗрдордзреНрдпреЗ рдпреЗрддрд╛рдд.

рдзрдбрд╛ 3. рд╣рдБрдбрд▓рдмрд╛рд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреЗ, рд╕рд╛рдЦрд│реА рд╡рдВрдЧрдг рдШрд╛рд▓рдгреЗ

рдкрд╛рд░реНрд╕рд░ рдкреВрд░реНрдг рд╣реЛрддрд╛рдЪ, рд╣рдБрдбрд▓рд░ рдкреНрд▓реЗрдордзреНрдпреЗ рдпреЗрддреЛ, рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рдкреБрдвреАрд▓ рд╕реВрдЪрдирд╛ рджреЗрддреЛ рдЖрдгрд┐ рдирд┐рдпрдВрддреНрд░рдг рджреЛрди рднрд╛рдЧрд╛рдВрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддреЛ.

рд╕рд╛рдзрд╛ рд╣рдБрдбрд▓рд░

using ClearServer.Core.UserController;
using System.Net.Security;
namespace ClearServer.Core.Requester
{
    public class RequestHandler
    {
        public static void OnHandle(SslStream ClientStream, RequestContext context)
        {

            if (context.CurrentUser != null)
            {
                new AuthUserController(ClientStream, context);
            }
            else 
            {
                new NonAuthUserController(ClientStream, context);
            };
        }
    }
}

рдЦрд░рдВ рддрд░, рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдЪреНрдпрд╛ рдЕрдзрд┐рдХреГрддрддреЗрд╕рд╛рдареА рдлрдХреНрдд рдПрдХ рддрдкрд╛рд╕рдгреА рдЖрд╣реЗ, рдЬреНрдпрд╛рдирдВрддрд░ рд╡рд┐рдирдВрддреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реБрд░реВ рд╣реЛрддреЗ.

рдХреНрд▓рд╛рдпрдВрдЯ рдХрдВрдЯреНрд░реЛрд▓рд░реНрд╕
рдЬрд░ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдЕрдзрд┐рдХреГрдд рдирд╕реЗрд▓, рддрд░ рддреНрдпрд╛рдЪреНрдпрд╛рд╕рд╛рдареА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗрд╡рд│ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдЖрдгрд┐ рдЕрдзрд┐рдХреГрдд рдиреЛрдВрджрдгреА рд╡рд┐рдВрдбреЛрдЪреНрдпрд╛ рдкреНрд░рджрд░реНрд╢рдирд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЖрд╣реЗ. рдЕрдзрд┐рдХреГрдд рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдЪрд╛ рдХреЛрдб рд╕рд╛рд░рдЦрд╛рдЪ рджрд┐рд╕рддреЛ, рдореНрд╣рдгреВрди рдорд▓рд╛ рддреЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХрд░рдгреНрдпрд╛рдЪреЗ рдХреЛрдгрддреЗрд╣реА рдХрд╛рд░рдг рджрд┐рд╕рдд рдирд╛рд╣реА.

рдЕрдирдзрд┐рдХреГрдд рд╡рд╛рдкрд░рдХрд░реНрддрд╛

using ClearServer.Core.Requester;
using System.IO;
using System.Net.Security;

namespace ClearServer.Core.UserController
{
    internal class NonAuthUserController
    {
        private readonly SslStream ClientStream;
        private readonly RequestContext Context;
        private readonly WriteController WriteController;
        private readonly AuthorizationController AuthorizationController;

        private readonly string ViewPath = "C:/Users/drdre/source/repos/ClearServer/View";

        public NonAuthUserController(SslStream clientStream, RequestContext context)
        {
            this.ClientStream = clientStream;
            this.Context = context;
            this.WriteController = new WriteController(clientStream);
            this.AuthorizationController = new AuthorizationController(clientStream, context);
            ResourceLoad();
        }

        void ResourceLoad()
        {
            string[] blockextension = new string[] {"cshtml", "html", "htm"};
            bool block = false;
            foreach (var item in blockextension)
            {
                if (Context.RequestUrl.Contains(item))
                {
                    block = true;
                    break;
                }
            }
            string FilePath = "";
            string Header = "";
            var RazorController = new RazorController(Context, ClientStream);
            
            switch (Context.RequestMethod)
            {
                case "GET":
                    switch (Context.RequestUrl)
                    {
                        case "/":
                            FilePath = ViewPath + "/loginForm.html";
                            Header =

quot;HTTP/1.1 200 OKnContent-Type: text/html";
WriteController.DefaultWriter(Header, FilePath);
break;
case "/profile":
RazorController.ProfileLoader(ViewPath);
break;
default:
//╨▓ ╨┤╨░╨╜╨╜╨╛╨╝ ╨▒╨╗╨╛╨║╨╡ ╨║╨╛╨┤╨░ ╨┐╤А╨╛╨╕╤Б╤Е╨╛╨┤╨╕╤В ╨╛╤В╤Б╨╡╤З╨╡╨╜╨╕╨╡ ╨╖╨░╨┐╤А╨╛╤Б╨╛╨▓ ╨║ ╤Б╨╡╤А╨▓╨╡╤А╤Г ╨┐╨╛ ╨┐╤А╤П╨╝╨╛╨╝╤Г ╨░╨┤╤А╨╡╤Б╤Г ╤Б╤В╤А╨░╨╜╨╕╤Ж╤Л ╨▓╨╕╨┤╨░ site.com/page.html
if (!File.Exists(ViewPath + Context.RequestUrl) | block)
{
RazorController.ErrorLoader(404);

}
else if (Path.HasExtension(Context.RequestUrl) && File.Exists(ViewPath + Context.RequestUrl))
{
Header = WriteController.ContentType(Context.RequestUrl);
FilePath = ViewPath + Context.RequestUrl;
WriteController.DefaultWriter(Header, FilePath);
}
break;
}
break;

case "POST":
AuthorizationController.MethodRecognizer();
break;

}

}

}
}

рдЖрдгрд┐ рдЕрд░реНрдерд╛рддрдЪ, рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рд╕ рдкреГрд╖реНрдард╛рдВрдЪреА рдХрд╛рд╣реА рд╕рд╛рдордЧреНрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ, рдореНрд╣рдгреВрди рдЙрддреНрддрд░рд╛рдВрд╕рд╛рдареА рдЦрд╛рд▓реАрд▓ рдореЙрдбреНрдпреВрд▓ рдЖрд╣реЗ, рдЬреЗ рд╕рдВрд╕рд╛рдзрдирд╛рдВрдЪреНрдпрд╛ рд╡рд┐рдирдВрддреАрд╕ рдкреНрд░рддрд┐рд╕рд╛рдж рджреЗрдгреНрдпрд╛рд╕рд╛рдареА рдЬрдмрд╛рдмрджрд╛рд░ рдЖрд╣реЗ.

рд▓реЗрдЦрдХ рдирд┐рдпрдВрддреНрд░рдХ

using System;
using System.IO;
using System.Net.Security;
using System.Text;

namespace ClearServer.Core.UserController
{
    public class WriteController
    {
        SslStream ClientStream;
        public WriteController(SslStream ClientStream)
        {
            this.ClientStream = ClientStream;
        }

        public void DefaultWriter(string Header, string FilePath)
        {
            FileStream fileStream;
            try
            {
                fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                Header =

quot;{Header}nContent-Length: {fileStream.Length}nn";
ClientStream.Write(Encoding.UTF8.GetBytes(Header));
byte[] response = new byte[fileStream.Length];
fileStream.BeginRead(response, 0, response.Length, OnFileRead, response);
}
catch { }
}

public string ContentType(string Uri)
{
string extension = Path.GetExtension(Uri);
string Header = "HTTP/1.1 200 OKnContent-Type:";
switch (extension)
{
case ".html":
case ".htm":
return


quot;{Header} text/html";
case ".css":
return


quot;{Header} text/css";
case ".js":
return


quot;{Header} text/javascript";
case ".jpg":
case ".jpeg":
case ".png":
case ".gif":
return


quot;{Header} image/{extension}";
default:
if (extension.Length > 1)
{
return


quot;{Header} application/" + extension.Substring(1);
}
else
{
return


quot;{Header} application/unknown";
}
}
}

public void OnFileRead(IAsyncResult ar)
{
if (ar.IsCompleted)
{
var file = (byte[])ar.AsyncState;
ClientStream.BeginWrite(file, 0, file.Length, OnClientSend, null);
}
}

public void OnClientSend(IAsyncResult ar)
{
if (ar.IsCompleted)
{
ClientStream.Close();
}
}
}

рдкрд░рдВрддреБ рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рд▓рд╛ рддреНрдпрд╛рдЪреЗ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдЖрдгрд┐ рдЗрддрд░ рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдВрдЪреЗ рдкреНрд░реЛрдлрд╛рдЗрд▓ рджрд░реНрд╢рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА, рдореА RazorEngine рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рдЪрд╛ рдХрд╛рд╣реА рднрд╛рдЧ рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪреЗ рдард░рд╡рд┐рд▓реЗ. рдпрд╛рдд рд╡рд╛рдИрдЯ рд╡рд┐рдирдВрддреНрдпрд╛ рд╣рд╛рддрд╛рд│рдгреЗ рдЖрдгрд┐ рдпреЛрдЧреНрдп рддреНрд░реБрдЯреА рдХреЛрдб рдЬрд╛рд░реА рдХрд░рдгреЗ рджреЗрдЦреАрд▓ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдЖрд╣реЗ.

рд░реЗрдЭрд░рдХрдВрдЯреНрд░реЛрд▓рд░

using ClearServer.Core.Requester;
using RazorEngine;
using RazorEngine.Templating;
using System;
using System.IO;
using System.Net;
using System.Net.Security;

namespace ClearServer.Core.UserController
{
    internal class RazorController
    {
        private RequestContext Context;
        private SslStream ClientStream;
        dynamic PageContent;


        public RazorController(RequestContext context, SslStream clientStream)
        {
            this.Context = context;
            this.ClientStream = clientStream;

        }

        public void ProfileLoader(string ViewPath)
        {
            string Filepath = ViewPath + "/profile.cshtml";
            if (Context.RequestProfile != null)
            {
                if (Context.CurrentUser != null && Context.RequestProfile.login == Context.CurrentUser.login)
                {
                    try
                    {
                        PageContent = new { isAuth = true, Name = Context.CurrentUser.name, Login = Context.CurrentUser.login, Skills = Context.CurrentUser.skills };
                        ClientSend(Filepath, Context.CurrentUser.login);
                    }
                    catch (Exception e) { Console.WriteLine(e); }

                }
                else
                {
                    try
                    {
                        PageContent = new { isAuth = false, Name = Context.RequestProfile.name, Login = Context.RequestProfile.login, Skills = Context.RequestProfile.skills };
                        ClientSend(Filepath, "PublicProfile:"+ Context.RequestProfile.login);
                    }
                    catch (Exception e) { Console.WriteLine(e); }
                }
            }
            else
            {
                ErrorLoader(404);
            }


        }

        public void ErrorLoader(int Code)
        {
            try
            {
                PageContent = new { ErrorCode = Code, Message = ((HttpStatusCode)Code).ToString() };
                string ErrorPage = "C:/Users/drdre/source/repos/ClearServer/View/Errors/ErrorPage.cshtml";
                ClientSend(ErrorPage, Code.ToString());
            }
            catch { }

        }

        private void ClientSend(string FilePath, string Key)
        {
            var template = File.ReadAllText(FilePath);
            var result = Engine.Razor.RunCompile(template, Key, null, (object)PageContent);
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(result);
            ClientStream.BeginWrite(buffer, 0, buffer.Length, OnClientSend, ClientStream);
        }

        private void OnClientSend(IAsyncResult ar)
        {
            if (ar.IsCompleted)
            {
                ClientStream.Close();
            }
        }
    }
}

рдЖрдгрд┐ рдЕрд░реНрдерд╛рддрдЪ, рдЕрдзрд┐рдХреГрдд рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдВрдЪреНрдпрд╛ рд╕рддреНрдпрд╛рдкрдирд╛рд╕рд╛рдареА рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдЕрдзрд┐рдХреГрддрддрд╛ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдЕрдзрд┐рдХреГрддрддрд╛ рдореЙрдбреНрдпреВрд▓ рдбреЗрдЯрд╛рдмреЗрд╕рд╢реА рд╕рдВрд╡рд╛рдж рд╕рд╛рдзрддреЗ. рд╕рд╛рдЗрдЯрд╡рд░реАрд▓ рдлреЙрд░реНрдордордзреВрди рдкреНрд░рд╛рдкреНрдд рдХреЗрд▓реЗрд▓рд╛ рдбреЗрдЯрд╛ рд╕рдВрджрд░реНрднрд╛рддреВрди рдкрд╛рд░реНрд╕ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ, рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рдЬрддрди рдХреЗрд▓рд╛ рдЬрд╛рддреЛ рдЖрдгрд┐ рдХреБрдХреАрдЬ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЛ рдЖрдгрд┐ рддреНрдпрд╛ рдмрджрд▓реНрдпрд╛рдд рд╕реЗрд╡реЗрдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЛ.

рдЕрдзрд┐рдХреГрддрддрд╛ рдореЙрдбреНрдпреВрд▓

using ClearServer.Core.Cookies;
using ClearServer.Core.Requester;
using ClearServer.Core.Security;
using System;
using System.Linq;
using System.Net.Security;
using System.Text;

namespace ClearServer.Core.UserController
{
    internal class AuthorizationController
    {
        private SslStream ClientStream;
        private RequestContext Context;
        private UserCookies cookies;
        private WriteController WriteController;
        DatabaseWorker DatabaseWorker;
        RazorController RazorController;
        PasswordHasher PasswordHasher;
        public AuthorizationController(SslStream clientStream, RequestContext context)
        {
            ClientStream = clientStream;
            Context = context;
            DatabaseWorker = new DatabaseWorker();
            WriteController = new WriteController(ClientStream);
            RazorController = new RazorController(context, clientStream);
            PasswordHasher = new PasswordHasher();
        }

        internal void MethodRecognizer()
        {
            if (Context.FormValues.Count == 2 && Context.FormValues.Any(x => x.Name == "password")) Authorize();
            else if (Context.FormValues.Count == 3 && Context.FormValues.Any(x => x.Name == "regPass")) Registration();
            else
            {
                RazorController.ErrorLoader(401);
            }
        }

        private void Authorize()
        {
            var values = Context.FormValues;
            var user = new User()
            {
                login = values[0].Value,
                password = PasswordHasher.PasswordHash(values[1].Value)
            };
            user = DatabaseWorker.UserAuth(user);
            if (user != null)
            {
                cookies = new UserCookies(user.login, user.password);
                user.cookie = cookies.AuthCookie;
                DatabaseWorker.UserUpdate(user);
                var response = Encoding.UTF8.GetBytes(

quot;HTTP/1.1 301 Moved PermanentlynLocation: /@{user.login}nSet-Cookie: {cookies.AuthCookie}; Expires={DateTime.Now.AddDays(2):R}; Secure; HttpOnlynn");
ClientStream.BeginWrite(response, 0, response.Length, WriteController.OnClientSend, null);

}
else
{
RazorController.ErrorLoader(401);

}
}

private void Registration()
{
var values = Context.FormValues;
var user = new User()
{
name = values[0].Value,
login = values[1].Value,
password = PasswordHasher.PasswordHash(values[2].Value),
};
cookies = new UserCookies(user.login, user.password);
user.cookie = cookies.AuthCookie;
if (DatabaseWorker.LoginValidate(user.login))
{
Console.WriteLine("User ready");
Console.WriteLine(


quot;{user.password} {user.password.Trim().Length}");
DatabaseWorker.UserRegister(user);
var response = Encoding.UTF8.GetBytes(


quot;HTTP/1.1 301 Moved PermanentlynLocation: /@{user.login}nSet-Cookie: {user.cookie}; Expires={DateTime.Now.AddDays(2):R}; Secure; HttpOnlynn");
ClientStream.BeginWrite(response, 0, response.Length, WriteController.OnClientSend, null);
}
else
{
RazorController.ErrorLoader(401);
}
}
}
}

рдЖрдгрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдЕрд╕рд╛ рджрд┐рд╕рддреЛ:

рдбреЗрдЯрд╛рдмреЗрд╕

using ClearServer.Core.UserController;
using System;
using System.Data.Linq;
using System.Linq;

namespace ClearServer
{
    class DatabaseWorker
    {

        private readonly Table<User> users = null;
        private readonly DataContext DataBase = null;
        private const string connectionStr = @"╨┐╤Г╤В╤М╨║╨▒╨░╨╖╨╡";

        public DatabaseWorker()
        {
            DataBase = new DataContext(connectionStr);
            users = DataBase.GetTable<User>();
        }

        public User UserAuth(User User)
        {
            try
            {
                var user = users.SingleOrDefault(t => t.login.ToLower() == User.login.ToLower() && t.password == User.password);
                if (user != null)
                    return user;
                else
                    return null;
            }
            catch (Exception)
            {
                return null;
            }

        }

        public void UserRegister(User user)
        {
            try
            {
                users.InsertOnSubmit(user);
                DataBase.SubmitChanges();
                Console.WriteLine(

quot;User{user.name} with id {user.uid} added");
foreach (var item in users)
{
Console.WriteLine(item.login + "n");
}
}
catch (Exception e)
{
Console.WriteLine(e);
}

}

public bool LoginValidate(string login)
{
if (users.Any(x => x.login.ToLower() == login.ToLower()))
{
Console.WriteLine("Login already exists");
return false;
}
return true;
}
public void UserUpdate(User user)
{
var UserToUpdate = users.FirstOrDefault(x => x.uid == user.uid);
UserToUpdate = user;
DataBase.SubmitChanges();
Console.WriteLine(


quot;User {UserToUpdate.name} with id {UserToUpdate.uid} updated");
foreach (var item in users)
{
Console.WriteLine(item.login + "n");
}
}
public User CookieValidate(string CookieInput)
{
User user = null;
try
{
user = users.SingleOrDefault(x => x.cookie == CookieInput);
}
catch
{
return null;
}
if (user != null) return user;
else return null;
}
public User FindUser(string login)
{
User user = null;
try
{
user = users.Single(x => x.login.ToLower() == login.ToLower());
if (user != null)
{
return user;
}
else
{
return null;
}
}
catch (Exception)
{
return null;
}
}
}
}


рдЖрдгрд┐ рд╕рд░реНрд╡рдХрд╛рд╣реА рдШрдбреНрдпрд╛рд│рд╛рдЪреЗ рдХрд╛рдо, рдЕрдзрд┐рдХреГрддрддрд╛ рдЖрдгрд┐ рдиреЛрдВрджрдгреА рдХрд╛рд░реНрдп рдпрд╛рд╕рд╛рд░рдЦреЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ, рд╕реЗрд╡реЗрдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢рд╛рдЪреА рдХрд┐рдорд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЖрдзреАрдЪ рдЙрдкрд▓рдмреНрдз рдЖрд╣реЗ рдЖрдгрд┐ рдЕрд░реНрдЬ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рд╕рдВрдкреВрд░реНрдг рдЧреЛрд╖реНрдЯ рдореБрдЦреНрдп рдлрдВрдХреНрд╢рдиреНрд╕рд╕рд╣ рдмрд╛рдВрдзрдгреНрдпрд╛рдЪреА рд╡реЗрд│ рдЖрд▓реА рдЖрд╣реЗ рдЬреНрдпрд╛рд╕рд╛рдареА рд╕рд░реНрд╡рдХрд╛рд╣реА рдХреЗрд▓реЗ рдЬрд╛рддреЗ.

рдзрдбрд╛ 4

рджреЛрди рдкреНрд▓реЕрдЯрдлреЙрд░реНрдорд╕рд╛рдареА рджреЛрди рдЕрд░реНрдЬ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЪрд╛ рдордЬреВрд░ рдЦрд░реНрдЪ рдХрдореА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдореА Xamarin.Forms рд╡рд░ рдХреНрд░реЙрд╕-рдкреНрд▓реЕрдЯрдлреЙрд░реНрдо рдмрдирд╡рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддрд▓рд╛. рдкреБрдиреНрд╣рд╛, рддреЗ C# рдордзреНрдпреЗ рдЕрд╕рд▓реНрдпрд╛рдмрджреНрджрд▓ рдзрдиреНрдпрд╡рд╛рдж. рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдлрдХреНрдд рдбреЗрдЯрд╛ рдкрд╛рдард╡рдгрд╛рд░рд╛ рдЪрд╛рдЪрдгреА рдЕрд░реНрдЬ рдХреЗрд▓реНрдпрд╛рд╡рд░, рдореА рдПрдХрд╛ рдордиреЛрд░рдВрдЬрдХ рдХреНрд╖рдгрд╛рдд рдЧреЗрд▓реЛ. рдбрд┐рд╡реНрд╣рд╛рдЗрд╕рдЪреНрдпрд╛ рд╡рд┐рдирдВрддреАрд╕рд╛рдареА, рдЧрдВрдордд рдореНрд╣рдгреВрди, рдореА рддреЗ HttpClient рд╡рд░ рд▓рд╛рдЧреВ рдХреЗрд▓реЗ рдЖрдгрд┐ HttpRequestMessage рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдЯрд╛рдХрд▓реЗ рдЬреНрдпрд╛рдордзреНрдпреЗ json рд╕реНрд╡рд░реВрдкрд╛рдд рдЕрдзрд┐рдХреГрддрддрд╛ рдлреЙрд░реНрдордЪрд╛ рдбреЗрдЯрд╛ рдЖрд╣реЗ. рд╡рд┐рд╢реЗрд╖рдд: рдХрд╢рд╛рдЪреАрд╣реА рдЕрдкреЗрдХреНрд╖рд╛ рди рдХрд░рддрд╛, рдореА рд╕рд░реНрд╡реНрд╣рд░ рд▓реЙрдЧ рдЙрдШрдбрд▓рд╛ рдЖрдгрд┐ рддреЗрдереЗ рд╕рд░реНрд╡ рдбреЗрдЯрд╛рд╕рд╣ рдбрд┐рд╡реНрд╣рд╛рдЗрд╕рдХрдбреВрди рд╡рд┐рдирдВрддреА рдкрд╛рд╣рд┐рд▓реА. рд╣рд▓рдХреА рд╕реНрддрдмреНрдзрддрд╛, рдЧреЗрд▓реНрдпрд╛ 3 рдЖрдард╡рдбреНрдпрд╛рдВрдЪреНрдпрд╛ рдирд┐рд╕реНрддреЗрдЬ рд╕рдВрдзреНрдпрд╛рдХрд╛рд│рдордзреНрдпреЗ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЧреЛрд╖реНрдЯреАрдЪреА рдЬрд╛рдгреАрд╡. рдкрд╛рдард╡рд▓реЗрд▓реНрдпрд╛ рдбреЗрдЯрд╛рдЪреА рд╢реБрджреНрдзрддрд╛ рддрдкрд╛рд╕рдгреНрдпрд╛рд╕рд╛рдареА, рдореА HttpListner рд╡рд░ рдЪрд╛рдЪрдгреА рд╕рд░реНрд╡реНрд╣рд░ рдПрдХрддреНрд░ рдХреЗрд▓рд╛. рддреНрдпрд╛рд╡рд░ рдЖрдзреАрдЪ рдкреБрдвреАрд▓ рд╡рд┐рдирдВрддреА рдкреНрд░рд╛рдкреНрдд рдЭрд╛рд▓реНрдпрд╛рдирдВрддрд░, рдореА рдХреЛрдбрдЪреНрдпрд╛ рджреЛрди рдУрд│реАрдВрдордзреНрдпреЗ рддреЗ рд╡реЗрдЧрд│реЗ рдХреЗрд▓реЗ, рдлреЙрд░реНрдордордзреВрди KeyValuePair рдбреЗрдЯрд╛ рдорд┐рд│рд╡рд▓рд╛. рдХреНрд╡реЗрд░реА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рджреЛрди рдУрд│реАрдВрдкрд░реНрдпрдВрдд рдХрдореА рдХреЗрд▓реА.

рдореА рдкреБрдвреАрд▓ рдЪрд╛рдЪрдгреА рд╕реБрд░реВ рдХреЗрд▓реА, рдпрд╛рдЪрд╛ рдЖрдзреА рдЙрд▓реНрд▓реЗрдЦ рдХреЗрд▓рд╛ рдЧреЗрд▓рд╛ рдирд╛рд╣реА, рдкрд░рдВрддреБ рдорд╛рдЧреАрд▓ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдореА рдЕрджреНрдпрд╛рдк рд╡реЗрдмрд╕реЙрдХреЗрдЯреНрд╕рд╡рд░ рддрдпрд╛рд░ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдЪреЕрдЯрдЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХреЗрд▓реА. рд╣реЗ рдЦреВрдкрдЪ рдЪрд╛рдВрдЧрд▓реЗ рдХрд╛рдо рдХреЗрд▓реЗ, рдкрд░рдВрддреБ Tcp рджреНрд╡рд╛рд░реЗ рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рджрд╛рдЪреЗ рддрддреНрддреНрд╡ рдирд┐рд░рд╛рд╢рд╛рдЬрдирдХ рд╣реЛрддреЗ, рдкрддреНрд░рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдЪреНрдпрд╛ рд▓реЙрдЧрд┐рдВрдЧрд╕рд╣ рджреЛрди рд╡рд╛рдкрд░рдХрд░реНрддреНрдпрд╛рдВрдЪрд╛ рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рдж рдпреЛрдЧреНрдпрд░рд┐рддреНрдпрд╛ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЦреВрдк рдЬрд╛рд╕реНрдд рдЙрддреНрдкрд╛рджрди рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧрд▓реЗ. рдпрд╛рдордзреНрдпреЗ рдХрдиреЗрдХреНрд╢рди рд╕реНрд╡рд┐рдЪрд┐рдВрдЧрдЪреНрдпрд╛ рд╡рд┐рдирдВрддреАрдЪреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдгреЗ рдЖрдгрд┐ RFC 6455 рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╡рд╛рдкрд░реВрди рдкреНрд░рддрд┐рд╕рд╛рдж рд╕рдВрдХрд▓рд┐рдд рдХрд░рдгреЗ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдЖрд╣реЗ. рдореНрд╣рдгреВрди, рдЪрд╛рдЪрдгреА рд╕рд░реНрд╡реНрд╣рд░рдордзреНрдпреЗ, рдореА рдПрдХ рд╕рд╛рдзреЗ рд╡реЗрдмрд╕реЙрдХреЗрдЯ рдХрдиреЗрдХреНрд╢рди рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддрд▓рд╛. рдирд┐рд╡реНрд╡рд│ рд╣рд┐рддрд╛рд╕рд╛рдареА.

рдЪреЕрдЯ рдХрдиреЗрдХреНрд╢рди

 private static async void HandleWebsocket(HttpListenerContext context)
        {
            var socketContext = await context.AcceptWebSocketAsync(null);
            var socket = socketContext.WebSocket;
            Locker.EnterWriteLock();
            try
            {
                Clients.Add(socket);
            }
            finally
            {
                Locker.ExitWriteLock();
            }

            while (true)
            {
                var buffer = new ArraySegment<byte>(new byte[1024]);
                var result = await socket.ReceiveAsync(buffer, CancellationToken.None);
                var str = Encoding.Default.GetString(buffer);
                Console.WriteLine(str);

                for (int i = 0; i < Clients.Count; i++)
                {
                    WebSocket client = Clients[i];

                    try
                    {
                        if (client.State == WebSocketState.Open)
                        {
                            
                            await client.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        Locker.EnterWriteLock();
                        try
                        {
                            Clients.Remove(client);
                            i--;
                        }
                        finally
                        {
                            Locker.ExitWriteLock();
                        }
                    }
                }
            }
        }

рдЖрдгрд┐ рддреЗ рдХрд╛рдо рдХреЗрд▓реЗ. рд╕рд░реНрд╡реНрд╣рд░рдиреЗ рд╕реНрд╡рддрдГ рдХрдиреЗрдХреНрд╢рди рд╕реЗрдЯ рдХреЗрд▓реЗ, рдкреНрд░рддрд┐рд╕рд╛рдж рдХреА рд╡реНрдпреБрддреНрдкрдиреНрди рдХреЗрд▓реА. рдорд▓рд╛ рдПрд╕рдПрд╕рдПрд▓ рджреНрд╡рд╛рд░реЗ рд╕рд░реНрд╡реНрд╣рд░ рдиреЛрдВрджрдгреА рд╕реНрд╡рддрдВрддреНрд░рдкрдгреЗ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рдЪреА рджреЗрдЦреАрд▓ рдЧрд░рдЬ рдирд╡реНрд╣рддреА, рд╣реЗ рдкреБрд░реЗрд╕реЗ рдЖрд╣реЗ рдХреА рд╕рд┐рд╕реНрдЯрдордХрдбреЗ рдЖрдзреАрдкрд╛рд╕реВрдирдЪ рдЖрд╡рд╢реНрдпрдХ рдкреЛрд░реНрдЯрд╡рд░ рдкреНрд░рдорд╛рдгрдкрддреНрд░ рд╕реНрдерд╛рдкрд┐рдд рдХреЗрд▓реЗ рдЖрд╣реЗ.

рдбрд┐рд╡реНрд╣рд╛рдЗрд╕рдЪреНрдпрд╛ рдмрд╛рдЬреВрд▓рд╛ рдЖрдгрд┐ рд╕рд╛рдЗрдЯрдЪреНрдпрд╛ рдмрд╛рдЬреВрд▓рд╛, рджреЛрди рдХреНрд▓рд╛рдпрдВрдЯрдиреЗ рд╕рдВрджреЗрд╢рд╛рдВрдЪреА рджреЗрд╡рд╛рдгрдШреЗрд╡рд╛рдг рдХреЗрд▓реА, рд╣реЗ рд╕рд░реНрд╡ рд▓реЙрдЧ рдХреЗрд▓реЗ рдЧреЗрд▓реЗ. рд╕рд░реНрд╡реНрд╣рд░ рдзреАрдорд╛ рдХрд░рдгрд╛рд░реЗ рдХреЛрдгрддреЗрд╣реА рдкреНрд░рдЪрдВрдб рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдирд╛рд╣реАрдд, рдпрд╛рдкреИрдХреА рдХрд╛рд╣реАрд╣реА рдЖрд╡рд╢реНрдпрдХ рдирд╡реНрд╣рддреЗ. рдкреНрд░рддрд┐рд╕рд╛рдж рд╡реЗрд│ 200ms рд╡рд░реВрди 40-30ms рдкрд░реНрдпрдВрдд рдХрдореА рдХреЗрд▓рд╛ рдЖрд╣реЗ. рдЖрдгрд┐ рдореА рдлрдХреНрдд рдпреЛрдЧреНрдп рдирд┐рд░реНрдгрдпрд╛рд╡рд░ рдЖрд▓реЛ.

C# .Net рдлреНрд░реЗрдорд╡рд░реНрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдкреНрд░рдЧрдд рд╕рд╛рдпрдХрд▓рд┐рдВрдЧ рдХрд┐рдВрд╡рд╛ рдХреНрд▓рд╛рдпрдВрдЯ-рд╕рд░реНрд╡реНрд╣рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ

Tcp рд╡рд░ рд╡рд░реНрддрдорд╛рди рд╕рд░реНрд╡реНрд╣рд░ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдлреЗрдХреВрди рджреНрдпрд╛ рдЖрдгрд┐ Http рдЕрдВрддрд░реНрдЧрдд рд╕рд░реНрд╡рдХрд╛рд╣реА рдкреБрдиреНрд╣рд╛ рд▓рд┐рд╣рд╛. рдЖрддрд╛ рдкреНрд░рдХрд▓реНрдк рдкреБрдиреНрд╣рд╛ рдбрд┐рдЭрд╛рдЗрдирдЪреНрдпрд╛ рдЯрдкреНрдкреНрдпрд╛рд╡рд░ рдЖрд╣реЗ, рдкрд░рдВрддреБ рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рджрд╛рдЪреНрдпрд╛ рдкреВрд░реНрдгрдкрдгреЗ рднрд┐рдиреНрди рддрддреНрддреНрд╡рд╛рдВрдиреБрд╕рд╛рд░. рдбрд┐рд╡реНрд╣рд╛рдЗрд╕реЗрд╕ рдЖрдгрд┐ рд╕рд╛рдЗрдЯрдЪреЗ рдСрдкрд░реЗрд╢рди рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЭ рдЖрдгрд┐ рдбреАрдмрдЧ рдХреЗрд▓реЗрд▓реЗ рдЖрд╣реЗ рдЖрдгрд┐ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрдХрд▓реНрдкрдирд╛ рдЖрд╣реЗ, рдлрдХреНрдд рдлрд░рдХ рдЖрд╣реЗ рдХреА рдбрд┐рд╡реНрд╣рд╛рдЗрд╕реЗрд╕рдирд╛ html рдкреГрд╖реНрдареЗ рд╡реНрдпреБрддреНрдкрдиреНрди рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╛рд╣реА.

рдирд┐рд╖реНрдХрд░реНрд╖

"рдлреЙрд░реНрдб рдорд╛рд╣рд┐рдд рдирд╛рд╣реА, рдкрд╛рдгреНрдпрд╛рдд рдбреЛрдХреЗ рдЯрд╛рдХреВ рдирдХрд╛" рдорд▓рд╛ рд╡рд╛рдЯрддреЗ, рдХрд╛рдо рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдкреВрд░реНрд╡реА, рдореА рдзреНрдпреЗрдпреЗ рдЖрдгрд┐ рдЙрджреНрджрд┐рд╖реНрдЯреЗ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХреЗрд▓реА рдкрд╛рд╣рд┐рдЬреЗрдд, рддрд╕реЗрдЪ рд╡рд┐рд╡рд┐рдз рдХреНрд▓рд╛рдпрдВрдЯрд╡рд░ рддреНрдпрд╛рдВрдЪреНрдпрд╛ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрд╕рд╛рдареА рдЖрд╡рд╢реНрдпрдХ рддрдВрддреНрд░рдЬреНрдЮрд╛рди рдЖрдгрд┐ рдкрджреНрдзрддреАрдВрдЪрд╛ рдЕрднреНрдпрд╛рд╕ рдХреЗрд▓рд╛ рдкрд╛рд╣рд┐рдЬреЗ. рдкреНрд░рдХрд▓реНрдк рдЖрдзреАрдЪ рдкреВрд░реНрдг рд╣реЛрдгреНрдпрд╛рдЪреНрдпрд╛ рдЬрд╡рд│ рдЖрд╣реЗ, рдкрд░рдВрддреБ рдХрджрд╛рдЪрд┐рдд рдореА рдХрд╛рд╣реА рдЧреЛрд╖реНрдЯреА рдкреБрдиреНрд╣рд╛ рдХрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ рдЦрд░рд╛рдм рдХреЗрд▓реНрдпрд╛ рдпрд╛рдмрджреНрджрд▓ рдмреЛрд▓рдгреНрдпрд╛рд╕рд╛рдареА рдореА рдкрд░рдд рдпреЗрдИрди. рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпреЗрджрд░рдореНрдпрд╛рди рдореА рдмрд░реЗрдЪ рдХрд╛рд╣реА рд╢рд┐рдХрд▓реЛ, рдкрд░рдВрддреБ рднрд╡рд┐рд╖реНрдпрд╛рдд рд╢рд┐рдХрдгреНрдпрд╛рд╕рд╛рд░рдЦреЗ рдмрд░реЗрдЪ рдХрд╛рд╣реА рдЖрд╣реЗ. рдЖрдкрдг рдЖрддрд╛рдкрд░реНрдпрдВрдд рд╡рд╛рдЪрд▓реЗ рдЕрд╕рд▓реНрдпрд╛рд╕, рд╡рд╛рдЪрд▓реНрдпрд╛рдмрджреНрджрд▓ рдзрдиреНрдпрд╡рд╛рдж.

рд╕реНрддреНрд░реЛрдд: www.habr.com