Advertisement
Guest User

Untitled

a guest
Nov 4th, 2020
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.13 KB | None | 0 0
  1. namespace ServerLib
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using System.Net;
  6.     using System.Net.Sockets;
  7.  
  8.     internal static class Log
  9.     {
  10.         internal static void Message(string message)
  11.         {
  12.             WriteToConsole(ConsoleColor.White, "MSG", message);
  13.         }
  14.         internal static void Error(string message)
  15.         {
  16.             WriteToConsole(ConsoleColor.Red, "ERR", message);
  17.         }
  18.  
  19.         private static void WriteToConsole(ConsoleColor fontColor, string level, string message)
  20.         {
  21.             Console.ForegroundColor = fontColor;
  22.             Console.WriteLine($"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}| [{level}] |>> {message}");
  23.             Console.ResetColor();
  24.         }
  25.     }
  26.  
  27.     public enum ServerState
  28.     {
  29.         Undef,
  30.         Started,
  31.         Stopped
  32.     }
  33.  
  34.     public interface IServer
  35.     {
  36.         public ServerState State { get; }
  37.         public void Start();
  38.         public void Stop();
  39.     }
  40.  
  41.     public interface IAcceptor
  42.     {
  43.         public event Action<Socket> ClientAccepted;
  44.         public bool IsStarted { get; }
  45.         public void Start();
  46.         public void Stop();
  47.     }
  48.  
  49.     public interface IHandler
  50.     {
  51.         public event Action<Socket> ClientDisconnected;
  52.         public event Action<Socket, IMessage> ClientMessageAccepted;
  53.         public event Action<Socket, IMessage> ClientMessageSended;
  54.  
  55.         public void Handle(Socket clientSocket);
  56.     }
  57.    
  58.     public interface IMessage
  59.     {
  60.         public int Length { get; }
  61.     }
  62.  
  63.     public class SocketAcceptor : IAcceptor
  64.     {
  65.         private readonly string _host;
  66.         private readonly int _port;
  67.  
  68.         public SocketAcceptor(string host, int port)
  69.         {
  70.             _host = host;
  71.             _port = port;
  72.         }
  73.         public bool IsStarted { get; private set; }
  74.  
  75.         public event Action<Socket> ClientAccepted;
  76.  
  77.         public void Start()
  78.         {
  79.             if (IsStarted) throw new InvalidOperationException("Acceptor alrady started");
  80.             IsStarted = true;
  81.             AcceptLoop();
  82.         }
  83.         public async void Stop()
  84.         {
  85.             if (!IsStarted) throw new InvalidOperationException("Acceptor not started");
  86.  
  87.             IsStarted = false;
  88.         }
  89.  
  90.         private async void AcceptLoop()
  91.         {
  92.             Socket acceptor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  93.             acceptor.Bind(new IPEndPoint(IPAddress.Parse(_host), _port));
  94.             acceptor.Listen(100);
  95.             try
  96.             {
  97. #if DEBUG
  98.                 Log.Message($"Start accept on {acceptor.LocalEndPoint}");
  99. #endif
  100.                 while (IsStarted)
  101.                 {
  102.                     Socket clientSocket = await acceptor.AcceptAsync();
  103. #if DEBUG
  104.                     Log.Message($"Accepted client {clientSocket.RemoteEndPoint}");
  105. #endif
  106.                     ClientAccepted?.Invoke(clientSocket);
  107.                 }
  108.             }
  109.             finally
  110.             {
  111.                 try
  112.                 {
  113.                     acceptor.Shutdown(SocketShutdown.Both);
  114.                 }
  115.                 finally
  116.                 {
  117.                     acceptor.Close();
  118.                 }
  119.             }
  120.  
  121.         }
  122.     }
  123.  
  124.     public class EchoHandler : IHandler
  125.     {
  126.         public event Action<Socket> ClientDisconnected;
  127.         public event Action<Socket, IMessage> ClientMessageAccepted;
  128.         public event Action<Socket, IMessage> ClientMessageSended;
  129.  
  130.         internal class RawMsg : IMessage
  131.         {
  132.             public int Length { get; set; }
  133.         }
  134.         public async void Handle(Socket clientSocket)
  135.         {
  136.             if(clientSocket.Connected)
  137.             {
  138.                 Memory<byte> buffer = new byte[1024];
  139.                 while(clientSocket.Available > 0)
  140.                 {
  141.                     int msgLen = await clientSocket.ReceiveAsync(buffer, SocketFlags.None);
  142.                     ClientMessageAccepted?.Invoke(clientSocket, new RawMsg { Length = msgLen });
  143.  
  144.                     await clientSocket.SendAsync(buffer.Slice(0, msgLen), SocketFlags.None);
  145.                     ClientMessageSended?.Invoke(clientSocket, new RawMsg { Length = msgLen });
  146.                 }
  147.             }
  148.             clientSocket.Shutdown(SocketShutdown.Both);
  149.             clientSocket.Close();
  150.             ClientDisconnected?.Invoke(clientSocket);
  151.         }
  152.     }
  153.     public class ServerBase : IServer
  154.     {
  155.         private readonly HashSet<Socket> _clients;
  156.         private readonly IAcceptor _acceptor;
  157.         private readonly IHandler _handler;
  158.  
  159.         public ServerBase(IAcceptor acceptor, IHandler handler)
  160.         {
  161.             _acceptor = acceptor ?? throw new ArgumentNullException(nameof(acceptor));
  162.             _handler = handler ?? throw new ArgumentNullException(nameof(handler));
  163.             _clients = new HashSet<Socket>();
  164.         }
  165.  
  166.         #region IServer
  167.  
  168.  
  169.         //-----------------------------------------------------------------------------------------
  170.        
  171.         public ServerState State { get; private set; }
  172.  
  173.         //-----------------------------------------------------------------------------------------
  174.  
  175.         public void Start()
  176.         {
  177.             if(State == ServerState.Started) throw new InvalidOperationException("Server alrady started.");
  178.             SubscribeOnHandlerEvents();
  179.             StartAccepor();
  180.             State = ServerState.Started;
  181.         }
  182.  
  183.         //-----------------------------------------------------------------------------------------
  184.  
  185.         public void Stop()
  186.         {
  187.             if(State != ServerState.Started) throw new InvalidOperationException("Server not started.");
  188.             UnsubscribeOnHandlerEvents();
  189.             StopAcceptor();
  190.             State = ServerState.Stopped;
  191.         }
  192.  
  193.         //-----------------------------------------------------------------------------------------
  194.  
  195.         #endregion IServer
  196.  
  197.         protected virtual void OnCleintSocketAccpeted(Socket clientSocket)
  198.         {
  199.             RegisterClient(clientSocket);
  200.             _handler.Handle(clientSocket);
  201.         }
  202.  
  203.         // Эти методы не должны использоваться для того чтобы закрывать сокеты или какую-то еще работу c клиентами производить,
  204.         // все это должно происходить в IHandler
  205.         // Данные методы должны использоваться для логгирования, ведения статистики и т.д.
  206.  
  207.         protected virtual void OnMessageAccepted(Socket clientSocket, IMessage message)
  208.         {
  209.             Log.Message($"{clientSocket.RemoteEndPoint} accepted {message.Length} bytes");
  210.         }
  211.         protected virtual void OnMessageSended(Socket clientSocket, IMessage message)
  212.         {
  213.             Log.Message($"{clientSocket.RemoteEndPoint} sended {message.Length} bytes");
  214.  
  215.         }
  216.         protected virtual void OnClientDisconnected(Socket clientSocket)
  217.         {
  218.             //Log.Message($"{clientSocket.RemoteEndPoint} disconnected");
  219.             UnregisterClient(clientSocket);
  220.         }
  221.  
  222.  
  223.         private void RegisterClient(Socket clientSocket)
  224.         {
  225.             _clients.Add(clientSocket);
  226.         }
  227.         private void UnregisterClient(Socket clientSocket)
  228.         {
  229.             _clients.Remove(clientSocket);
  230.         }
  231.         private void StartAccepor()
  232.         {          
  233.             _acceptor.ClientAccepted += OnCleintSocketAccpeted;
  234.             _acceptor.Start();
  235.         }
  236.         private void StopAcceptor()
  237.         {
  238.             _acceptor.ClientAccepted -= OnCleintSocketAccpeted;
  239.             _acceptor.Stop();
  240.         }
  241.         private void SubscribeOnHandlerEvents()
  242.         {
  243.             _handler.ClientMessageAccepted += OnMessageAccepted;
  244.             _handler.ClientMessageSended += OnMessageSended;
  245.             _handler.ClientDisconnected += OnClientDisconnected;
  246.         }
  247.         private void UnsubscribeOnHandlerEvents()
  248.         {
  249.             _handler.ClientMessageAccepted -= OnMessageAccepted;
  250.             _handler.ClientMessageSended -= OnMessageSended;
  251.             _handler.ClientDisconnected -= OnClientDisconnected;
  252.         }
  253.     }
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement