C# .Net ಚೌಕಟ್ಟಿನ ಆಧಾರದ ಮೇಲೆ ಸುಧಾರಿತ ಬೈಸಿಕಲ್ ಕಟ್ಟಡ ಅಥವಾ ಕ್ಲೈಂಟ್-ಸರ್ವರ್ ಅಪ್ಲಿಕೇಶನ್

ಪ್ರವೇಶ

ನಾನು ಸಣ್ಣ ವೆಬ್ ಸೇವೆಯನ್ನು ರಚಿಸಲು ಸಹೋದ್ಯೋಗಿ ಸೂಚಿಸಿದಾಗ ಇದು ಪ್ರಾರಂಭವಾಯಿತು. ಇದು ಟಿಂಡರ್‌ನಂತೆಯೇ ಇರಬೇಕಿತ್ತು, ಆದರೆ ಐಟಿ ಗುಂಪಿಗೆ. ಕಾರ್ಯವು ತುಂಬಾ ಸರಳವಾಗಿದೆ, ನೀವು ನೋಂದಾಯಿಸಿ, ಪ್ರೊಫೈಲ್ ಅನ್ನು ಭರ್ತಿ ಮಾಡಿ ಮತ್ತು ಮುಖ್ಯ ಅಂಶಕ್ಕೆ ಮುಂದುವರಿಯಿರಿ, ಅವುಗಳೆಂದರೆ ಮಾತನಾಡಲು ವ್ಯಕ್ತಿಯನ್ನು ಹುಡುಕುವುದು ಮತ್ತು ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ವಿಸ್ತರಿಸುವುದು ಮತ್ತು ಹೊಸ ಪರಿಚಯಸ್ಥರನ್ನು ಮಾಡುವುದು.

ಇಲ್ಲಿ ನಾನು ಹಿಮ್ಮೆಟ್ಟಬೇಕು ಮತ್ತು ನನ್ನ ಬಗ್ಗೆ ಸ್ವಲ್ಪ ಹೇಳಬೇಕು, ಇದರಿಂದ ಭವಿಷ್ಯದಲ್ಲಿ ನಾನು ಅಭಿವೃದ್ಧಿಯಲ್ಲಿ ಅಂತಹ ಕ್ರಮಗಳನ್ನು ಏಕೆ ತೆಗೆದುಕೊಂಡೆ ಎಂಬುದು ಹೆಚ್ಚು ಸ್ಪಷ್ಟವಾಗುತ್ತದೆ.

ಈ ಸಮಯದಲ್ಲಿ ನಾನು ಒಂದು ಗೇಮ್ ಸ್ಟುಡಿಯೋದಲ್ಲಿ ತಾಂತ್ರಿಕ ಕಲಾವಿದನ ಸ್ಥಾನವನ್ನು ಹೊಂದಿದ್ದೇನೆ, C# ನಲ್ಲಿ ನನ್ನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ ಅನುಭವವನ್ನು ಯೂನಿಟಿಗಾಗಿ ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು ಮತ್ತು ಉಪಯುಕ್ತತೆಗಳನ್ನು ಬರೆಯುವುದರ ಮೇಲೆ ಮಾತ್ರ ನಿರ್ಮಿಸಲಾಗಿದೆ ಮತ್ತು ಇದರ ಜೊತೆಗೆ, Android ಸಾಧನಗಳೊಂದಿಗೆ ಕಡಿಮೆ-ಮಟ್ಟದ ಕೆಲಸಕ್ಕಾಗಿ ಪ್ಲಗಿನ್‌ಗಳನ್ನು ರಚಿಸುವುದು. ನಾನು ಇನ್ನೂ ಈ ಪುಟ್ಟ ಪ್ರಪಂಚವನ್ನು ಮೀರಿ ಸಾಹಸ ಮಾಡಿರಲಿಲ್ಲ, ಮತ್ತು ನಂತರ ಅಂತಹ ಅವಕಾಶವು ಹುಟ್ಟಿಕೊಂಡಿತು.

ಭಾಗ 1. ಫ್ರೇಮ್ ಮೂಲಮಾದರಿ

ಈ ಸೇವೆ ಹೇಗಿರುತ್ತದೆ ಎಂದು ನಿರ್ಧರಿಸಿದ ನಂತರ, ನಾನು ಅನುಷ್ಠಾನಕ್ಕೆ ಆಯ್ಕೆಗಳನ್ನು ಹುಡುಕಲು ಪ್ರಾರಂಭಿಸಿದೆ. ಕೆಲವು ರೀತಿಯ ಸಿದ್ಧ ಪರಿಹಾರವನ್ನು ಕಂಡುಹಿಡಿಯುವುದು ಸುಲಭವಾದ ವಿಷಯವಾಗಿದೆ, ಅದರ ಮೇಲೆ, ಗ್ಲೋಬ್ನಲ್ಲಿ ಗೂಬೆಯಂತೆ, ನಮ್ಮ ಯಂತ್ರಶಾಸ್ತ್ರವನ್ನು ಎಳೆಯಬಹುದು ಮತ್ತು ಇಡೀ ವಿಷಯವನ್ನು ಸಾರ್ವಜನಿಕ ಖಂಡನೆಗೆ ಒಡ್ಡಬಹುದು.
ಆದರೆ ಇದು ಆಸಕ್ತಿದಾಯಕವಲ್ಲ, ನಾನು ಅದರಲ್ಲಿ ಯಾವುದೇ ಸವಾಲು ಅಥವಾ ಅರ್ಥವನ್ನು ನೋಡಲಿಲ್ಲ ಮತ್ತು ಆದ್ದರಿಂದ ನಾನು ವೆಬ್ ತಂತ್ರಜ್ಞಾನಗಳು ಮತ್ತು ಅವರೊಂದಿಗೆ ಸಂವಹನ ಮಾಡುವ ವಿಧಾನಗಳನ್ನು ಅಧ್ಯಯನ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಿದೆ.

ನಾನು C# .Net ನಲ್ಲಿ ಲೇಖನಗಳು ಮತ್ತು ದಾಖಲಾತಿಗಳನ್ನು ನೋಡುವ ಮೂಲಕ ಅಧ್ಯಯನವನ್ನು ಪ್ರಾರಂಭಿಸಿದೆ. ಇಲ್ಲಿ ನಾನು ಕೆಲಸವನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ವಿವಿಧ ಮಾರ್ಗಗಳನ್ನು ಕಂಡುಕೊಂಡಿದ್ದೇನೆ. ASP.Net ಅಥವಾ Azure ಸೇವೆಗಳಂತಹ ಪೂರ್ಣ ಪ್ರಮಾಣದ ಪರಿಹಾರಗಳಿಂದ TcpHttp ಸಂಪರ್ಕಗಳೊಂದಿಗೆ ನೇರ ಸಂವಾದದವರೆಗೆ ನೆಟ್‌ವರ್ಕ್‌ನೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಹಲವು ಕಾರ್ಯವಿಧಾನಗಳಿವೆ.

ಎಎಸ್ಪಿಯೊಂದಿಗೆ ನನ್ನ ಮೊದಲ ಪ್ರಯತ್ನವನ್ನು ಮಾಡಿದ ನಂತರ, ನಾನು ತಕ್ಷಣ ಅದನ್ನು ತಿರಸ್ಕರಿಸಿದೆ; ನನ್ನ ಅಭಿಪ್ರಾಯದಲ್ಲಿ, ಇದು ನಮ್ಮ ಸೇವೆಗೆ ತುಂಬಾ ಕಷ್ಟಕರವಾದ ನಿರ್ಧಾರವಾಗಿತ್ತು. ಈ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನ ಸಾಮರ್ಥ್ಯಗಳಲ್ಲಿ ಮೂರನೇ ಒಂದು ಭಾಗವನ್ನು ಸಹ ನಾವು ಬಳಸುವುದಿಲ್ಲ, ಆದ್ದರಿಂದ ನಾನು ನನ್ನ ಹುಡುಕಾಟವನ್ನು ಮುಂದುವರೆಸಿದೆ. ಆಯ್ಕೆಯು TCP ಮತ್ತು Http ಕ್ಲೈಂಟ್-ಸರ್ವರ್ ನಡುವೆ ಇತ್ತು. ಇಲ್ಲಿ, ಹಬ್ರೆಯಲ್ಲಿ, ನಾನು ಲೇಖನವನ್ನು ನೋಡಿದೆ ಮಲ್ಟಿಥ್ರೆಡ್ ಸರ್ವರ್, ಅದನ್ನು ಸಂಗ್ರಹಿಸಿ ಮತ್ತು ಪರೀಕ್ಷಿಸಿದ ನಂತರ, 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 ರೂಪದ ಒಂದು ಶ್ರೇಣಿಗೆ ಹಾಕುತ್ತೇವೆ ಮತ್ತು ನಾವು ಅದೇ ರೀತಿಯ ಶ್ರೇಣಿಯಲ್ಲಿ ಇರಿಸಲಾದ ಯಾವುದಾದರೂ ವಿಷಯವನ್ನು (ಉದಾಹರಣೆಗೆ, ಕ್ವೆರಿಸ್ಟ್ರಿಂಗ್) ಹುಡುಕುತ್ತೇವೆ. ಹೆಚ್ಚುವರಿಯಾಗಿ, ಪಾರ್ಸರ್ ಪ್ರಸ್ತುತ ಕ್ಲೈಂಟ್ ಅಧಿಕೃತವಾಗಿದೆಯೇ ಮತ್ತು ಅವರ ಡೇಟಾವನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆಯೇ ಎಂದು ಕಂಡುಕೊಳ್ಳುತ್ತದೆ. ಅಧಿಕೃತ ಕ್ಲೈಂಟ್‌ಗಳಿಂದ ಎಲ್ಲಾ ವಿನಂತಿಗಳು ಅಧಿಕೃತ ಹ್ಯಾಶ್ ಅನ್ನು ಒಳಗೊಂಡಿರುತ್ತವೆ, ಅದನ್ನು ಕುಕೀಗಳಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ, ಇದಕ್ಕೆ ಧನ್ಯವಾದಗಳು ಎರಡು ರೀತಿಯ ಕ್ಲೈಂಟ್‌ಗಳಿಗೆ ಮತ್ತಷ್ಟು ಆಪರೇಟಿಂಗ್ ಲಾಜಿಕ್ ಅನ್ನು ಪ್ರತ್ಯೇಕಿಸಲು ಮತ್ತು ಅವರಿಗೆ ಸರಿಯಾದ ಉತ್ತರಗಳನ್ನು ನೀಡಲು ಸಾಧ್ಯವಿದೆ.

ಅಲ್ಲದೆ, ಪ್ರತ್ಯೇಕ ಮಾಡ್ಯೂಲ್‌ನಲ್ಲಿ ಹಾಕಲು ಯೋಗ್ಯವಾದ ಒಂದು ಸಣ್ಣ, ಉತ್ತಮವಾದ ವೈಶಿಷ್ಟ್ಯ, "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 ನಲ್ಲಿ ಕಾರ್ಯಗತಗೊಳಿಸಿದೆ ಮತ್ತು ಅದನ್ನು Json ಸ್ವರೂಪದಲ್ಲಿ ಅಧಿಕೃತ ಫಾರ್ಮ್‌ನಿಂದ ಡೇಟಾವನ್ನು ಒಳಗೊಂಡಿರುವ HttpRequestMessage ಸರ್ವರ್‌ಗೆ ಕಳುಹಿಸಿದೆ. ನಿರ್ದಿಷ್ಟವಾಗಿ ಏನನ್ನೂ ನಿರೀಕ್ಷಿಸದೆ, ನಾನು ಸರ್ವರ್ ಲಾಗ್ ಅನ್ನು ತೆರೆದಿದ್ದೇನೆ ಮತ್ತು ಎಲ್ಲಾ ಡೇಟಾದೊಂದಿಗೆ ಸಾಧನದಿಂದ ವಿನಂತಿಯನ್ನು ನೋಡಿದೆ. ಸ್ವಲ್ಪ ಮೂರ್ಖತನ, ಕಳೆದ 3 ವಾರಗಳಿಂದ ಮಾಡಿದ ಎಲ್ಲದರ ಅರಿವು ಸುಸ್ತಾಗುವ ಸಂಜೆ. ಕಳುಹಿಸಿದ ಡೇಟಾದ ನಿಖರತೆಯನ್ನು ಪರಿಶೀಲಿಸಲು, ನಾನು HttpListner ನಲ್ಲಿ ಪರೀಕ್ಷಾ ಸರ್ವರ್ ಅನ್ನು ಜೋಡಿಸಿದ್ದೇನೆ. ಅದರ ಮೇಲೆ ಈಗಾಗಲೇ ಮತ್ತೊಂದು ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿದ ನಂತರ, ನಾನು ಅದನ್ನು ಒಂದೆರಡು ಸಾಲುಗಳ ಕೋಡ್‌ನಲ್ಲಿ ತೆಗೆದುಕೊಂಡೆ ಮತ್ತು ಫಾರ್ಮ್‌ನಿಂದ ಡೇಟಾದ ಕೀವ್ಯಾಲ್ಯೂಪೇರ್ ಅನ್ನು ಸ್ವೀಕರಿಸಿದ್ದೇನೆ. ಪ್ರಶ್ನೆಯನ್ನು ಪಾರ್ಸಿಂಗ್ ಮಾಡುವುದನ್ನು ಎರಡು ಸಾಲುಗಳಿಗೆ ಇಳಿಸಲಾಗಿದೆ.

ನಾನು ಮತ್ತಷ್ಟು ಪರೀಕ್ಷೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿದೆ, ಇದನ್ನು ಮೊದಲೇ ಉಲ್ಲೇಖಿಸಲಾಗಿಲ್ಲ, ಆದರೆ ಹಿಂದಿನ ಸರ್ವರ್‌ನಲ್ಲಿ ನಾನು ವೆಬ್‌ಸಾಕೆಟ್‌ಗಳಲ್ಲಿ ನಿರ್ಮಿಸಲಾದ ಚಾಟ್ ಅನ್ನು ಸಹ ಕಾರ್ಯಗತಗೊಳಿಸಿದೆ. ಇದು ಸಾಕಷ್ಟು ಚೆನ್ನಾಗಿ ಕೆಲಸ ಮಾಡಿದೆ, ಆದರೆ 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