Babban hawan keke ko aikace-aikacen uwar garken abokin ciniki bisa tsarin C# .Net

Gabatarwa

Hakan ya fara ne lokacin da abokin aiki ya ba da shawarar cewa in yi ƙaramin sabis na gidan yanar gizo. Ya kamata ya zama wani abu kamar tinder, amma don hangout IT. Ayyukan yana da sauƙin sauƙi, kuna yin rajista, cika bayanin martaba kuma ku matsa zuwa babban batu, wato, nemo mai shiga tsakani da faɗaɗa haɗinku da yin sabbin abokai.

A nan dole ne in zurfafa kuma in ɗan faɗi kaɗan game da kaina, ta yadda nan gaba za a ƙara bayyana dalilin da yasa na ɗauki irin waɗannan matakan na ci gaba.

A halin yanzu ina riƙe matsayin mai fasaha na fasaha a cikin ɗakin wasan kwaikwayo, ƙwarewar shirye-shirye na C # ya dogara ne kawai akan rubuta rubutun da abubuwan amfani don Unity kuma, ban da wannan, ƙirƙirar plugins don ƙananan matakan aiki tare da na'urorin android. A wajen wannan ƙaramar duniyar, ban riga na zaɓi ba sannan na sami irin wannan damar.

Sashe na 1. Samfurin Samfura

Bayan yanke shawarar yadda wannan sabis ɗin zai kasance, na fara neman zaɓuɓɓuka don aiwatarwa. Hanya mafi sauƙi ita ce samun wani nau'i na shirye-shiryen da aka yi, wanda, kamar mujiya a duniya, za ku iya ja da makanikan mu kuma ku fitar da komai don cin mutuncin jama'a.
Amma wannan ba abin sha'awa ba ne, ban ga wani kalubale da ma'ana a cikin wannan ba, don haka na fara nazarin fasahar yanar gizo da hanyoyin mu'amala da su.

An fara binciken ne ta hanyar kallon labarai da takardu akan C # .Net. Anan na sami hanyoyi daban-daban don cim ma aikin. Akwai hanyoyi da yawa don yin hulɗa tare da hanyar sadarwa, daga cikakkun mafita kamar ASP.Net ko sabis na Azure, zuwa hulɗar kai tsaye tare da haɗin TcpHttp.

Bayan na yi ƙoƙari na farko tare da ASP, nan da nan na soke shi, a ganina yana da wuyar yanke shawara ga hidimarmu. Ba za mu yi amfani da ko da kashi uku na iyawar wannan dandali ba, don haka na ci gaba da bincike na. Zaɓin ya tashi tsakanin TCP da uwar garken abokin ciniki na Http. Anan, akan Habré, na sami labarin labarin uwar garken multithreaded, Bayan tattarawa da gwada wanda, na yanke shawarar mayar da hankali kan yin hulɗa tare da haɗin TCP, saboda wasu dalilai na yi tunanin cewa http ba zai ƙyale ni in ƙirƙiri mafita na giciye ba.

Sigar farko ta uwar garken ta haɗa da haɗin kai, yin hidima ga abubuwan da ke cikin shafin yanar gizo, da haɗa da bayanan mai amfani. Kuma don farawa, na yanke shawarar gina mai aiki don aiki tare da rukunin yanar gizon, ta yadda daga baya zan iya ɗaure sarrafa aikace-aikacen akan android da ios anan.

Ga wasu code
Babban zaren karɓar abokan ciniki a cikin madauki mara iyaka:

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

Mai kula da abokin ciniki kanta:

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

Kuma farkon bayanan da aka gina akan SQL na gida:

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

Kamar yadda kake gani, wannan sigar ta bambanta kadan daga wanda ke cikin labarin. A gaskiya ma, kawai zazzage shafuka daga babban fayil akan kwamfutar da kuma bayanan bayanan an ƙara su anan (wanda, ta hanyar, bai yi aiki a cikin wannan sigar ba, saboda tsarin haɗin haɗin da ba daidai ba).

Babi na 2

Bayan gwada uwar garken, na zo ga ƙarshe cewa wannan zai zama babban bayani (bata: a'a), don hidimarmu, don haka aikin ya fara samun dabaru.
Mataki zuwa mataki, sabbin kayayyaki sun fara bayyana kuma aikin uwar garken ya girma. Sabar ta sami yankin gwaji da ɓoyayyen haɗin ssl.

Ƙarin ƙarin lambar da ke kwatanta dabaru na uwar garken da sarrafa abokan ciniki
Sabunta sigar uwar garken, gami da amfani da takaddun shaida.

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

Haka kuma sabon mai kula da abokin ciniki tare da izini ta hanyar 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);
}

}
}

Amma tun da uwar garken yana aiki ne kawai akan haɗin TCP, ya zama dole don ƙirƙirar tsarin da zai iya gane mahallin buƙatar. Na yanke shawarar cewa parser ya dace a nan wanda zai karya buƙatar abokin ciniki zuwa sassa daban-daban waɗanda zan iya yin hulɗa tare da su don ba abokin ciniki amsoshin da suka dace.

Fassara

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

Asalinsa yana cikin gaskiyar cewa tare da taimakon maganganun yau da kullun don karya buƙatun cikin sassa. Muna karɓar saƙo daga abokin ciniki, zaɓi layin farko, wanda ya ƙunshi hanyar da buƙatar url. Sa'an nan kuma mu karanta rubutun kai, wanda muke turawa zuwa cikin jerin nau'i na nau'i na HeaderName = Content, kuma mu sami, idan akwai, abubuwan da ke tare da su (misali, querystring) wanda muke turawa zuwa cikin tsararru iri ɗaya. Bugu da ƙari, mai binciken yana gano idan abokin ciniki na yanzu yana da izini kuma ya adana bayanansa. Duk buƙatun daga abokan ciniki masu izini sun ƙunshi hash na izini, wanda aka adana a cikin kukis, godiya ga wanda zai yiwu a raba ƙarin dabaru na aiki don nau'ikan abokan ciniki guda biyu kuma a ba su amsoshin daidai.

Da kyau, ƙaramin abu mai kyau wanda yakamata a motsa shi zuwa wani keɓantaccen tsari, yana canza buƙatun kamar "site.com/@UserName" zuwa shafukan masu amfani da aka ƙirƙira. Bayan sarrafa buƙatun, waɗannan samfuran suna shiga cikin wasa.

Babi na 3. Shigar da sandar hannu, da shafa sarkar

Da zarar mai binciken ya gama, mai sarrafa ya shigo cikin wasa, yana ba da ƙarin umarni ga uwar garken kuma yana rarraba sarrafawa zuwa sassa biyu.

mai sauƙi mai kulawa

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

A zahiri, rajistan guda ɗaya ne kawai don izinin mai amfani, bayan haka ana fara aiwatar da buƙatar.

Masu Kula da Abokin Ciniki
Idan mai amfani ba shi da izini, to a gare shi aikin yana dogara ne kawai akan nunin bayanan mai amfani da taga rajistar izini. Lambar don mai amfani da izini yayi kama da iri ɗaya, don haka ban ga dalilin kwafi shi ba.

Mai amfani mara izini

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;

}

}

}
}

Kuma ba shakka, mai amfani dole ne ya sami wasu abubuwan da ke cikin shafukan, don haka don amsoshi akwai tsarin mai zuwa, wanda ke da alhakin amsa buƙatun albarkatun.

Marubuci Mai Gudanarwa

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

Amma don nuna wa mai amfani bayanin martabarsa da bayanan wasu masu amfani, na yanke shawarar yin amfani da RazorEngine, ko kuma wani ɓangare na shi. Hakanan ya haɗa da sarrafa munanan buƙatun da ba da lambar kuskuren da ta dace.

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

Kuma ba shakka, don tabbatar da masu amfani da izini suyi aiki, ana buƙatar izini. Tsarin izini yana hulɗa tare da bayanan bayanai. Ana rarraba bayanan da aka karɓa daga fom akan rukunin yanar gizon daga mahallin, an adana mai amfani kuma yana karɓar kukis da samun dama ga sabis ɗin a madadin.

Tsarin izini

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

Kuma wannan shine yadda rumbun adana bayanai suka yi kama:

Database

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


Kuma duk abin da ke aiki kamar agogon agogo, izini da aikin rajista, ƙaramin aiki na samun damar yin amfani da sabis ɗin ya riga ya kasance kuma lokaci yayi da za a rubuta aikace-aikacen kuma ƙulla duk abin tare da manyan ayyuka waɗanda aka yi komai.

Babi na 4

Don rage farashin aiki na rubuta aikace-aikace biyu don dandamali biyu, na yanke shawarar yin giciye-dandamali akan Xamarin.Forms. Bugu da ƙari, godiya ga gaskiyar cewa yana cikin C #. Bayan yin aikace-aikacen gwaji wanda kawai ke aika bayanai zuwa uwar garken, na shiga cikin lokaci mai ban sha'awa. Don buƙatu daga na'urar, don jin daɗi, na aiwatar da shi akan HttpClient kuma na jefa shi akan uwar garken HttpRequestMessage wanda ya ƙunshi bayanai daga fom ɗin izini a tsarin json. Ba tare da tsammanin wani abu ba musamman, na buɗe log ɗin uwar garken na ga buƙatu daga na'urar tare da duk bayanan da ke wurin. Hasken haske, sanin duk abin da aka yi a cikin makonni 3 da suka gabata na maraice maraice. Don duba daidaiton bayanan da aka aiko, na haɗa uwar garken gwaji akan HttpListner. Bayan samun buƙatu na gaba a kai, na ware shi a cikin layukan lamba biyu, na sami bayanan KeyValuePair daga sigar. Binciken tambaya ya ragu zuwa layi biyu.

Na fara gwadawa, ba a ambata a baya ba, amma a kan uwar garken da ta gabata har yanzu na aiwatar da hira da aka gina akan shafukan yanar gizo. Ya yi aiki da kyau, amma ainihin ƙa'idar hulɗa ta hanyar Tcp yana da ban tsoro, ƙari da yawa dole ne a samar da shi don gina hulɗar masu amfani biyu daidai tare da shigar da wasiku. Wannan ya haɗa da ƙaddamar da buƙatun don sauyawa haɗi da tattara amsa ta amfani da ka'idar RFC 6455. Saboda haka, a cikin uwar garken gwaji, na yanke shawarar ƙirƙirar haɗin yanar gizo mai sauƙi. Zalla domin sha'awa.

Haɗin taɗi

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

Kuma ya yi aiki. Sabar da kanta ta saita haɗin, ta haifar da maɓallin amsawa. Ba ma sai in saita rajistar uwar garken daban ta hanyar ssl, ya isa cewa tsarin ya riga ya shigar da takaddun shaida akan tashar da ake buƙata.

A gefen na'urar da kuma a gefen shafin, abokan ciniki biyu sun yi musayar sakonni, duk wannan an shigar da su. Babu manyan masu fastoci da ke rage sabar, babu ɗayan waɗannan da aka buƙata. An rage lokacin amsawa daga 200ms zuwa 40-30ms. Kuma na zo ga shawarar da ta dace kawai.

Babban hawan keke ko aikace-aikacen uwar garken abokin ciniki bisa tsarin C# .Net

Jefa aiwatar da sabar na yanzu akan Tcp kuma sake rubuta komai a ƙarƙashin Http. Yanzu aikin yana kan matakin sake fasalin, amma bisa ga ka'idodin hulɗar mabanbanta. Ayyukan na'urori da rukunin yanar gizon suna aiki tare kuma an cire su kuma suna da ra'ayi gama gari, tare da bambancin kawai cewa na'urori ba sa buƙatar samar da shafukan html.

ƙarshe

"Ban san ford ba, kar ka gyada kai cikin ruwa." Ina tsammanin, kafin fara aiki, ya kamata in ƙara bayyana maƙasudi da manufofi, da kuma zurfafa cikin nazarin fasahar da ake bukata da hanyoyin aiwatar da su a kan abokan ciniki daban-daban. An kusa kammala aikin, amma watakila zan dawo in yi magana kan yadda na sake murƙushe wasu abubuwa. Na koyi abubuwa da yawa yayin tsarin ci gaba, amma akwai ƙarin koyo a nan gaba. Idan kun karanta wannan zuwa yanzu, to na gode don karantawa.

source: www.habr.com