Avanse bilding bisiklèt oswa aplikasyon kliyan-sèvè ki baze sou C# .Net fondasyon

Antre

Tout bagay te kòmanse lè yon kòlèg te sijere ke mwen kreye yon ti sèvis entènèt. Li te sipoze yon bagay tankou Tinder, men pou foul moun yo IT. Fonksyonalite a trè senp, ou anrejistre, ranpli yon pwofil epi ale nan pwen prensipal la, sètadi jwenn yon moun pou pale ak elaji koneksyon ou ak fè nouvo zanmi.

Isit la mwen dwe fè yon retrè epi di ou yon ti kras sou tèt mwen, pou nan lavni li ta pi klè poukisa mwen te pran etap sa yo nan devlopman.

Nan moman sa a mwen kenbe pozisyon nan Atis Teknik nan yon sèl estidyo jwèt, eksperyans pwogram mwen an nan C# te bati sèlman sou ekri scripts ak sèvis piblik pou Unity epi, anplis sa a, kreye grefon pou travay ki ba nivo ak aparèy Android. Mwen pa t 'ko s'aventure pi lwen pase ti mond sa a, ak Lè sa a, yon opòtinite sa a te parèt.

Pati 1. Pwototip ankadreman

Lè m te deside ki jan sèvis sa a ta ye, mwen te kòmanse chèche opsyon pou aplikasyon an. Bagay ki pi fasil la ta dwe jwenn kèk kalite solisyon pare, sou ki, tankou yon chwèt sou yon glòb, mekanik nou yo ka rale ak tout bagay la ka ekspoze a sannman piblik.
Men, sa a pa enteresan, mwen pa t 'wè okenn defi oswa sans nan li, ak Se poutèt sa mwen te kòmanse etidye teknoloji entènèt ak metòd pou kominike avèk yo.

Mwen te kòmanse etidye nan gade atik ak dokiman sou C# .Net. Isit la mwen te jwenn plizyè fason pou konplete travay la. Gen anpil mekanis pou kominike avèk rezo a, soti nan solisyon konplè tankou ASP.Net oswa Azure sèvis, nan entèraksyon dirèk ak koneksyon TcpHttp.

Lè m te fè premye tantativ mwen ak ASP, mwen te rejte li imedyatman, sa te yon desizyon twò difisil pou sèvis nou an. Nou pa ta sèvi ak menm yon tyè nan kapasite platfòm sa a, kidonk mwen te kontinye rechèch mwen an. Chwa a te genyen ant TCP ak Http kliyan-sèvè. Isit la, sou Habré, mwen te rankontre yon atik sou sèvè multithreaded, li te kolekte epi teste li, mwen deside konsantre espesyalman sou entèraksyon ak koneksyon TCP, pou kèk rezon mwen te panse ke http pa ta pèmèt mwen kreye yon solisyon kwa-platfòm.

Premye vèsyon sèvè a enkli pwosesis koneksyon, te sèvi kontni paj wèb estatik, epi li gen ladan yon baz done itilizatè. E pou kòmanse, mwen deside bati fonksyonalite pou travay ak sit la, pou mwen te kapab pita ajoute pwosesis aplikasyon an sou android ak iOS.

Men kèk kòd
Fil prensipal la k ap resevwa kliyan nan yon bouk kontinuèl:

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);
        }
    }
}

Manadjè kliyan an tèt li:

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();
}
}
}


Ak premye baz done bati sou SQL lokal yo:
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}");
}
}
}
}
}


Kòm ou ka wè, vèsyon sa a diferan ti kras ak youn nan atik la. An reyalite, isit la nou jis ajoute loading nan paj ki soti nan yon katab sou òdinatè a ak yon baz done (ki, nan chemen an, pa t 'travay nan vèsyon sa a akòz achitekti a koneksyon kòrèk).

Chapit 2. Vis wou yo

Apre tès sèvè a, mwen te rive nan konklizyon ke sa a ta dwe yon solisyon ekselan (spoiler: non), pou sèvis nou an, se konsa pwojè a te kòmanse jwenn lojik.
Pa etap, nouvo modil yo te kòmanse parèt epi fonksyonalite sèvè a te elaji. Sèvè a te pran yon domèn tès epi SSL chifreman koneksyon.

Yon ti kras plis kòd ki dekri lojik sèvè a ak pwosesis kliyan an
Yon vèsyon mete ajou nan sèvè a ki gen ladan itilizasyon yon sètifika.

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();
        }
    }
}

Epi tou yon nouvo moun kap okipe kliyan ki gen otorizasyon 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);
}

}
}


Men, depi sèvè a kouri sèlman sou yon koneksyon TCP, li nesesè yo kreye yon modil ki ta ka rekonèt kontèks demann lan. Mwen te deside ke yon analizeur ta dwe apwopriye isit la ki ta kase demann lan soti nan kliyan an nan pati separe ak ki mwen te kapab kominike yo nan lòd yo bay kliyan an repons ki nesesè yo.

Analizeur

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;
}
}
}


Sans li se kraze demann lan an pati lè l sèvi avèk ekspresyon regilye. Nou resevwa yon mesaj nan men kliyan an, chwazi premye liy lan, ki gen metòd la ak demann url. Lè sa a, nou li tit yo, ke nou mete nan yon etalaj nan fòm nan HeaderName = Kontni, epi nou jwenn tou, si sa disponib, akonpaye kontni (pa egzanp, querystring) ke nou menm tou nou mete nan yon etalaj menm jan an. Anplis de sa, analizeur a chèche konnen si wi ou non kliyan aktyèl la otorize epi estoke done li yo. Tout demann ki soti nan kliyan otorize gen yon hash otorizasyon, ki estoke nan bonbon, gras a sa a li posib separe plis lojik opere pou de kalite kliyan yo epi ba yo repons ki kòrèk yo.

Oke, yon ti, bèl karakteristik ki ta vo mete nan yon modil separe, konvèsyon an nan demann tankou "site.com/@UserName" nan paj itilizatè ki jenere dinamik. Apre yo fin trete demann lan, modil sa yo antre nan jwèt.

Chapit 3. Enstale volan an, wilaj chèn lan

Le pli vit ke parser la fini travay li, moun kap okipe a antre nan jwèt, bay plis enstriksyon nan sèvè a ak divize kontwòl an de pati.

Manadjè senp

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);
            };
        }
    }
}

An reyalite, gen yon sèl chèk pou otorizasyon itilizatè, apre sa pwosesis demann lan kòmanse.

Kontwolè kliyan yo
Si itilizatè a pa otorize, Lè sa a, fonksyonalite a pou li baze sèlman sou montre pwofil itilizatè a ak fenèt enskripsyon otorizasyon an. Kòd pou yon itilizatè otorize sanble sou menm bagay la tou, kidonk mwen pa wè okenn rezon ki fè yo kopi li.

Itilizatè san otorizasyon

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;

}

}

}
}


Ak nan kou, itilizatè a dwe resevwa kèk kalite kontni paj, kidonk pou repons gen modil sa a, ki responsab pou reponn a demann resous yo.

WriterController

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();
}
}
}


Men, nan lòd yo montre itilizatè a pwofil li yo ak pwofil lòt itilizatè yo, mwen deside sèvi ak RazorEngine, oswa pito yon pati nan li. Li gen ladan tou trete demann envalid ak bay yon kòd erè apwopriye.

RazorController

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();
            }
        }
    }
}

Ak nan kou, nan lòd pou verifikasyon an nan itilizatè otorize yo travay, otorizasyon nesesè. Modil otorizasyon an reyaji ak baz done a. Done yo resevwa nan fòm sou sit la analize nan kontèks la, itilizatè a sove epi an retou resevwa bonbon ak aksè nan sèvis la.

Modil otorizasyon

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);
}
}
}
}


Ak sa a se sa pwosesis baz done sanble:

Baz done

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;
}
}
}
}


Ak tout bagay mache tankou revèy, travay otorizasyon ak anrejistreman, fonksyonalite minimòm pou jwenn aksè nan sèvis la deja la e lè a rive pou ekri yon aplikasyon epi mare tout bagay ansanm ak fonksyon prensipal yo pou tout bagay ap fèt.

Chapit 4. Jete bisiklèt la

Pou diminye depans travay yo nan ekri de aplikasyon pou de platfòm, mwen deside fè yon kwa-platfòm sou Xamarin.Forms. Yon fwa ankò, gras a lefèt ke li se nan C #. Èske w te fè yon aplikasyon tès ki tou senpleman voye done sou sèvè a, mwen te vin atravè yon pwen enteresan. Pou yon demann ki soti nan yon aparèy, pou plezi, mwen aplike li sou HttpClient epi voye li nan sèvè a HttpRequestMessage, ki gen done ki soti nan fòm otorizasyon nan fòma json. San yo pa patikilyèman atann anyen, mwen louvri boutèy demi lit sèvè a epi li wè gen yon demann ki soti nan aparèy la ak tout done yo. Yon ti kras stupèr, konsyans de tout sa ki te fèt pandan 3 semèn ki sot pase yo nan yon aswè lang. Pou tcheke presizyon nan done yo voye, mwen reyini yon sèvè tès sou HttpListner. Èske w te resevwa yon lòt demann deja sou li, mwen te pran li apa nan yon koup nan liy nan kòd epi mwen te resevwa yon KeyValuePair nan done ki soti nan fòm lan. Analiz rechèch la te redwi a de liy.

Mwen te kòmanse fè tès pi lwen, li pa te mansyone pi bonè, men sou sèvè anvan an mwen te aplike tou yon chat bati sou websockets. Li te travay byen, men prensip la nan entèraksyon atravè Tcp te depresyon te gen twòp travay nesesè yo dwe fè yo nan lòd yo bati entèraksyon an nan de itilizatè ak yon boutèy demi lit korespondans. Sa a gen ladan analize yon demann pou chanje koneksyon an ak kolekte yon repons lè l sèvi avèk pwotokòl la RFC 6455 Se poutèt sa, nan sèvè tès la, mwen deside kreye yon koneksyon websocket senp. Jis pou plezi.

Konekte pou chat

 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();
                        }
                    }
                }
            }
        }

Epi li te travay. Sèvè a tèt li configured koneksyon an ak pwodwi yon kle repons. Mwen pa t 'menm konfigirasyon separeman sèvè enskripsyon atravè SSL li te ase ke sistèm nan te deja enstale yon sètifika sou pò ki nesesè yo.

Sou bò aparèy la ak sou bò sit la, de kliyan echanj mesaj, tout bagay sa yo te konekte. Pa gen parseur gwo ralanti sèvè a, pa gen okenn nan sa a te obligatwa. Tan repons te diminye soti nan 200ms a 40-30ms. Apre sa, mwen te vin nan sèl desizyon an dwa.

Avanse bilding bisiklèt oswa aplikasyon kliyan-sèvè ki baze sou C# .Net fondasyon

Jete aplikasyon sèvè aktyèl la sou Tcp epi reekri tout bagay anba Http. Koulye a, pwojè a se nan etap nan redesign, men dapre prensip konplètman diferan nan entèraksyon. Se operasyon an nan aparèy ak sit la senkronize ak debogaj epi li gen yon konsèp komen, ak diferans lan sèlman ke pa gen okenn bezwen jenere paj HTML pou aparèy.

Sòti

"Si ou pa konnen ford la, pa antre nan dlo a" Mwen panse ke anvan yo kòmanse travay, mwen ta dwe gen pi klè defini objektif ak objektif, osi byen ke fouye nan etid la nan teknoloji ki nesesè yo ak metòd pou aplikasyon yo sou kliyan divès kalite. Pwojè a deja prèske fini, men petèt mwen pral tounen pale sou fason mwen sove kèk bagay ankò. Mwen te aprann anpil bagay pandan pwosesis devlopman an, men gen plis toujou pou aprann nan tan kap vini an. Si ou te li byen lwen, di ou mèsi pou fè sa.

Sous: www.habr.com

Achte hosting serye pou sit ki gen pwoteksyon DDoS, sèvè VPS VDS 🔥 Achte yon hébergement sit entènèt serye ak pwoteksyon DDoS, sèvè VPS VDS | ProHoster