Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace ServerLib
- {
- using System;
- using System.Collections.Generic;
- using System.Net;
- using System.Net.Sockets;
- internal static class Log
- {
- internal static void Message(string message)
- {
- WriteToConsole(ConsoleColor.White, "MSG", message);
- }
- internal static void Error(string message)
- {
- WriteToConsole(ConsoleColor.Red, "ERR", message);
- }
- private static void WriteToConsole(ConsoleColor fontColor, string level, string message)
- {
- Console.ForegroundColor = fontColor;
- Console.WriteLine($"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}| [{level}] |>> {message}");
- Console.ResetColor();
- }
- }
- public enum ServerState
- {
- Undef,
- Started,
- Stopped
- }
- public interface IServer
- {
- public ServerState State { get; }
- public void Start();
- public void Stop();
- }
- public interface IAcceptor
- {
- public event Action<Socket> ClientAccepted;
- public bool IsStarted { get; }
- public void Start();
- public void Stop();
- }
- public interface IHandler
- {
- public event Action<Socket> ClientDisconnected;
- public event Action<Socket, IMessage> ClientMessageAccepted;
- public event Action<Socket, IMessage> ClientMessageSended;
- public void Handle(Socket clientSocket);
- }
- public interface IMessage
- {
- public int Length { get; }
- }
- public class SocketAcceptor : IAcceptor
- {
- private readonly string _host;
- private readonly int _port;
- public SocketAcceptor(string host, int port)
- {
- _host = host;
- _port = port;
- }
- public bool IsStarted { get; private set; }
- public event Action<Socket> ClientAccepted;
- public void Start()
- {
- if (IsStarted) throw new InvalidOperationException("Acceptor alrady started");
- IsStarted = true;
- AcceptLoop();
- }
- public async void Stop()
- {
- if (!IsStarted) throw new InvalidOperationException("Acceptor not started");
- IsStarted = false;
- }
- private async void AcceptLoop()
- {
- Socket acceptor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- acceptor.Bind(new IPEndPoint(IPAddress.Parse(_host), _port));
- acceptor.Listen(100);
- try
- {
- #if DEBUG
- Log.Message($"Start accept on {acceptor.LocalEndPoint}");
- #endif
- while (IsStarted)
- {
- Socket clientSocket = await acceptor.AcceptAsync();
- #if DEBUG
- Log.Message($"Accepted client {clientSocket.RemoteEndPoint}");
- #endif
- ClientAccepted?.Invoke(clientSocket);
- }
- }
- finally
- {
- try
- {
- acceptor.Shutdown(SocketShutdown.Both);
- }
- finally
- {
- acceptor.Close();
- }
- }
- }
- }
- public class EchoHandler : IHandler
- {
- public event Action<Socket> ClientDisconnected;
- public event Action<Socket, IMessage> ClientMessageAccepted;
- public event Action<Socket, IMessage> ClientMessageSended;
- internal class RawMsg : IMessage
- {
- public int Length { get; set; }
- }
- public async void Handle(Socket clientSocket)
- {
- if(clientSocket.Connected)
- {
- Memory<byte> buffer = new byte[1024];
- while(clientSocket.Available > 0)
- {
- int msgLen = await clientSocket.ReceiveAsync(buffer, SocketFlags.None);
- ClientMessageAccepted?.Invoke(clientSocket, new RawMsg { Length = msgLen });
- await clientSocket.SendAsync(buffer.Slice(0, msgLen), SocketFlags.None);
- ClientMessageSended?.Invoke(clientSocket, new RawMsg { Length = msgLen });
- }
- }
- clientSocket.Shutdown(SocketShutdown.Both);
- clientSocket.Close();
- ClientDisconnected?.Invoke(clientSocket);
- }
- }
- public class ServerBase : IServer
- {
- private readonly HashSet<Socket> _clients;
- private readonly IAcceptor _acceptor;
- private readonly IHandler _handler;
- public ServerBase(IAcceptor acceptor, IHandler handler)
- {
- _acceptor = acceptor ?? throw new ArgumentNullException(nameof(acceptor));
- _handler = handler ?? throw new ArgumentNullException(nameof(handler));
- _clients = new HashSet<Socket>();
- }
- #region IServer
- //-----------------------------------------------------------------------------------------
- public ServerState State { get; private set; }
- //-----------------------------------------------------------------------------------------
- public void Start()
- {
- if(State == ServerState.Started) throw new InvalidOperationException("Server alrady started.");
- SubscribeOnHandlerEvents();
- StartAccepor();
- State = ServerState.Started;
- }
- //-----------------------------------------------------------------------------------------
- public void Stop()
- {
- if(State != ServerState.Started) throw new InvalidOperationException("Server not started.");
- UnsubscribeOnHandlerEvents();
- StopAcceptor();
- State = ServerState.Stopped;
- }
- //-----------------------------------------------------------------------------------------
- #endregion IServer
- protected virtual void OnCleintSocketAccpeted(Socket clientSocket)
- {
- RegisterClient(clientSocket);
- _handler.Handle(clientSocket);
- }
- // Эти методы не должны использоваться для того чтобы закрывать сокеты или какую-то еще работу c клиентами производить,
- // все это должно происходить в IHandler
- // Данные методы должны использоваться для логгирования, ведения статистики и т.д.
- protected virtual void OnMessageAccepted(Socket clientSocket, IMessage message)
- {
- Log.Message($"{clientSocket.RemoteEndPoint} accepted {message.Length} bytes");
- }
- protected virtual void OnMessageSended(Socket clientSocket, IMessage message)
- {
- Log.Message($"{clientSocket.RemoteEndPoint} sended {message.Length} bytes");
- }
- protected virtual void OnClientDisconnected(Socket clientSocket)
- {
- //Log.Message($"{clientSocket.RemoteEndPoint} disconnected");
- UnregisterClient(clientSocket);
- }
- private void RegisterClient(Socket clientSocket)
- {
- _clients.Add(clientSocket);
- }
- private void UnregisterClient(Socket clientSocket)
- {
- _clients.Remove(clientSocket);
- }
- private void StartAccepor()
- {
- _acceptor.ClientAccepted += OnCleintSocketAccpeted;
- _acceptor.Start();
- }
- private void StopAcceptor()
- {
- _acceptor.ClientAccepted -= OnCleintSocketAccpeted;
- _acceptor.Stop();
- }
- private void SubscribeOnHandlerEvents()
- {
- _handler.ClientMessageAccepted += OnMessageAccepted;
- _handler.ClientMessageSended += OnMessageSended;
- _handler.ClientDisconnected += OnClientDisconnected;
- }
- private void UnsubscribeOnHandlerEvents()
- {
- _handler.ClientMessageAccepted -= OnMessageAccepted;
- _handler.ClientMessageSended -= OnMessageSended;
- _handler.ClientDisconnected -= OnClientDisconnected;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement