Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using NLog;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- namespace Network
- {
- public static class TcpServer
- {
- private static readonly Logger _log = LogManager.GetCurrentClassLogger();
- private static readonly HashSet<Thread> _listeningThreads = new HashSet<Thread>();
- private static readonly Socket _listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- private static ObjectsPool<Client> _connectionsPool;
- public static void Initialize()
- {
- _connectionsPool = new ObjectsPool<Client>(Program.NetConfig.MaxConnections);
- _listeningSocket.Bind(new IPEndPoint(IPAddress.Parse(Program.NetConfig.Host), Program.NetConfig.Port));
- _listeningSocket.Listen(Program.NetConfig.BackLog);
- for (int i = 0; i < Program.NetConfig.AcceptThreads; i++)
- {
- var th = new Thread(() => _listeningSocket.BeginAccept(AcceptCallback, null));
- th.Start();
- _listeningThreads.Add(th);
- }
- _log.Info("Server listening started..");
- }
- private static void AcceptCallback(IAsyncResult ar)
- {
- Socket sock = null;
- try
- {
- sock = _listeningSocket.EndAccept(ar);
- var connection = _connectionsPool.Get();
- if (connection == null)
- _log.Warn("Connections limit reached! Can't accept new connection");
- else
- {
- _log.Info($"Client {sock.RemoteEndPoint} connected!");
- connection.Socket = sock;
- connection.Socket.BeginReceive(connection.WaitPacketLength, 0, 128, SocketFlags.None, ReadCallback, connection);
- }
- }
- catch (Exception)
- {
- sock?.Close();
- }
- _listeningSocket.BeginAccept(AcceptCallback, null);
- }
- private static void ReadCallback(IAsyncResult ar)
- {
- var connection = (Client)ar.AsyncState;
- try
- {
- var readed = connection.Socket.EndReceive(ar, out var err);
- if (err != SocketError.Success || readed <= 0)
- {
- connection.Release();
- connection.Socket.Disconnect(false);
- connection.Socket.Close();
- _connectionsPool.Release(connection);
- return;
- }
- var buf = connection.WaitPacketLength;
- var len = BitConverter.ToUInt16(buf, 0);
- var opcode = (ushort)BitConverter.ToInt16(buf, 2);
- if (len > 0)
- {
- var packetDataBuffer = new byte[len - 4];
- if (len - 4 > 0)
- {
- var r = 0;
- do
- r += connection.Socket.Receive(packetDataBuffer, r, packetDataBuffer.Length - r, SocketFlags.None);
- while (r < packetDataBuffer.Length);
- }
- ProtocolHandler.ProceedFrame(connection, opcode, packetDataBuffer);
- }
- else
- {
- connection.Socket.BeginReceive(connection.WaitPacketLength, 0, connection.WaitPacketLength.Length, SocketFlags.None, ReadCallback, connection);
- return;
- }
- connection.Socket.BeginReceive(connection.WaitPacketLength, 0, connection.WaitPacketLength.Length, SocketFlags.None, ReadCallback, connection);
- }
- catch (ObjectDisposedException)
- {
- }
- catch (Exception e)
- {
- if (connection != null)
- Disconnect(connection);
- _log.Error(e);
- }
- }
- public static void Disconnect(Client client)
- {
- try
- {
- client.Release();
- client.Socket.BeginDisconnect(false, EndDisconect, client);
- }
- catch (Exception e)
- {
- _log.Error($"Exception occured on begin disconnect, {e}");
- }
- }
- private static void EndDisconect(IAsyncResult ar)
- {
- var connection = (Client)ar.AsyncState;
- try
- {
- connection.Socket.EndDisconnect(ar);
- }
- catch (Exception e)
- {
- _log.Error($"Exception occured on end disconnect, {e}");
- }
- finally
- {
- _log.Debug($"Client {connection.Socket.RemoteEndPoint.ToString()} disconnected.");
- connection.Socket.Close();
- _connectionsPool.Release(connection);
- }
- }
- public static void ProceedFrameToClient(Guid netIdentity, ASendFrame sendFrame)
- {
- var activeConnections = _connectionsPool?.GetUsedObjects();
- if(activeConnections != null)
- activeConnections.FirstOrDefault(s => s.NetIdentity == netIdentity)?.SendFrame(sendFrame);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement