Advertisement
Guest User

Simple async tcp server

a guest
Apr 6th, 2020
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.42 KB | None | 0 0
  1. using NLog;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Threading;
  8.  
  9. namespace Network
  10. {
  11.     public static class TcpServer
  12.     {
  13.         private static readonly Logger _log = LogManager.GetCurrentClassLogger();
  14.         private static readonly HashSet<Thread> _listeningThreads = new HashSet<Thread>();
  15.         private static readonly Socket _listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  16.  
  17.         private static ObjectsPool<Client> _connectionsPool;
  18.        
  19.         public static void Initialize()
  20.         {
  21.             _connectionsPool = new ObjectsPool<Client>(Program.NetConfig.MaxConnections);
  22.             _listeningSocket.Bind(new IPEndPoint(IPAddress.Parse(Program.NetConfig.Host), Program.NetConfig.Port));
  23.             _listeningSocket.Listen(Program.NetConfig.BackLog);
  24.  
  25.             for (int i = 0; i < Program.NetConfig.AcceptThreads; i++)
  26.             {
  27.                 var th = new Thread(() => _listeningSocket.BeginAccept(AcceptCallback, null));
  28.                 th.Start();
  29.                 _listeningThreads.Add(th);
  30.             }
  31.             _log.Info("Server listening started..");
  32.         }
  33.  
  34.         private static void AcceptCallback(IAsyncResult ar)
  35.         {
  36.             Socket sock = null;
  37.  
  38.             try
  39.             {
  40.                 sock = _listeningSocket.EndAccept(ar);
  41.  
  42.                 var connection = _connectionsPool.Get();
  43.                 if (connection == null)
  44.                     _log.Warn("Connections limit reached! Can't accept new connection");
  45.                 else
  46.                 {
  47.                     _log.Info($"Client {sock.RemoteEndPoint} connected!");
  48.  
  49.                     connection.Socket = sock;
  50.                     connection.Socket.BeginReceive(connection.WaitPacketLength, 0, 128, SocketFlags.None, ReadCallback, connection);
  51.      
  52.                 }
  53.             }
  54.             catch (Exception)
  55.             {
  56.                 sock?.Close();
  57.             }
  58.  
  59.             _listeningSocket.BeginAccept(AcceptCallback, null);
  60.         }
  61.  
  62.  
  63.         private static void ReadCallback(IAsyncResult ar)
  64.         {
  65.             var connection = (Client)ar.AsyncState;
  66.  
  67.             try
  68.             {
  69.                 var readed = connection.Socket.EndReceive(ar, out var err);
  70.                 if (err != SocketError.Success || readed <= 0)
  71.                 {
  72.                     connection.Release();
  73.                     connection.Socket.Disconnect(false);
  74.                     connection.Socket.Close();
  75.                     _connectionsPool.Release(connection);
  76.                     return;
  77.                 }
  78.                 var buf = connection.WaitPacketLength;
  79.                 var len = BitConverter.ToUInt16(buf, 0);
  80.                 var opcode = (ushort)BitConverter.ToInt16(buf, 2);
  81.                 if (len > 0)
  82.                 {
  83.                     var packetDataBuffer = new byte[len - 4];
  84.  
  85.                     if (len - 4 > 0)
  86.                     {
  87.                         var r = 0;
  88.                         do
  89.                             r += connection.Socket.Receive(packetDataBuffer, r, packetDataBuffer.Length - r, SocketFlags.None);
  90.                         while (r < packetDataBuffer.Length);
  91.                     }
  92.  
  93.                     ProtocolHandler.ProceedFrame(connection, opcode, packetDataBuffer);
  94.                 }
  95.                 else
  96.                 {
  97.                     connection.Socket.BeginReceive(connection.WaitPacketLength, 0, connection.WaitPacketLength.Length, SocketFlags.None, ReadCallback, connection);
  98.                     return;
  99.                 }
  100.  
  101.                 connection.Socket.BeginReceive(connection.WaitPacketLength, 0, connection.WaitPacketLength.Length, SocketFlags.None, ReadCallback, connection);
  102.             }
  103.             catch (ObjectDisposedException)
  104.             {
  105.             }
  106.             catch (Exception e)
  107.             {
  108.                 if (connection != null)
  109.                     Disconnect(connection);
  110.  
  111.                 _log.Error(e);
  112.             }
  113.         }
  114.  
  115.         public static void Disconnect(Client client)
  116.         {
  117.             try
  118.             {
  119.                 client.Release();
  120.                 client.Socket.BeginDisconnect(false, EndDisconect, client);
  121.             }
  122.             catch (Exception e)
  123.             {
  124.                 _log.Error($"Exception occured on begin disconnect, {e}");
  125.             }
  126.         }
  127.  
  128.         private static void EndDisconect(IAsyncResult ar)
  129.         {
  130.             var connection = (Client)ar.AsyncState;
  131.  
  132.             try
  133.             {
  134.                 connection.Socket.EndDisconnect(ar);
  135.             }
  136.             catch (Exception e)
  137.             {
  138.                 _log.Error($"Exception occured on end disconnect, {e}");
  139.             }
  140.             finally
  141.             {
  142.                 _log.Debug($"Client {connection.Socket.RemoteEndPoint.ToString()} disconnected.");
  143.                 connection.Socket.Close();
  144.                 _connectionsPool.Release(connection);
  145.             }
  146.         }
  147.  
  148.         public static void ProceedFrameToClient(Guid netIdentity, ASendFrame sendFrame)
  149.         {
  150.             var activeConnections = _connectionsPool?.GetUsedObjects();
  151.             if(activeConnections != null)
  152.                 activeConnections.FirstOrDefault(s => s.NetIdentity == netIdentity)?.SendFrame(sendFrame);            
  153.         }
  154.     }
  155. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement