Advertisement
Khaos_Theory

Buffered Server C#

Jun 22nd, 2013
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.17 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.Sockets;
  4. using System.Net;
  5. using System.ComponentModel;
  6. using System.IO;
  7.  
  8. //------------------
  9. //Creator: aeonhack
  10. //Site: nimoru.com
  11. //Name: Buffered Server
  12. //Created: 9/12/2012
  13. //Changed: 6/13/2013
  14. //Version: 1.2.0.3
  15. //------------------
  16. //Converted to C# by Khaos Theory
  17.  
  18. sealed class ServerClient : IDisposable
  19. {
  20.  
  21.     //TODO: Lock objects where needed.
  22.     //TODO: Create and handle ReadQueue?
  23.     //TODO: Provide option to disable buffering.
  24.  
  25.     #region " Events "
  26.  
  27.     public event ExceptionThrownEventHandler ExceptionThrown;
  28.     public delegate void ExceptionThrownEventHandler(ServerClient sender, Exception ex);
  29.  
  30.     private void OnExceptionThrown(Exception ex)
  31.     {
  32.         if (ExceptionThrown != null)
  33.         {
  34.             ExceptionThrown(this, ex);
  35.         }
  36.     }
  37.  
  38.     public event StateChangedEventHandler StateChanged;
  39.     public delegate void StateChangedEventHandler(ServerClient sender, bool connected);
  40.  
  41.     private void OnStateChanged(bool connected)
  42.     {
  43.         if (StateChanged != null)
  44.         {
  45.             StateChanged(this, connected);
  46.         }
  47.     }
  48.  
  49.     public event ReadPacketEventHandler ReadPacket;
  50.     public delegate void ReadPacketEventHandler(ServerClient sender, byte[] data);
  51.  
  52.     private void OnReadPacket(byte[] data)
  53.     {
  54.         if (ReadPacket != null)
  55.         {
  56.             ReadPacket(this, data);
  57.         }
  58.     }
  59.  
  60.     public event ReadProgressChangedEventHandler ReadProgressChanged;
  61.     public delegate void ReadProgressChangedEventHandler(ServerClient sender, double progress, int bytesRead, int bytesToRead);
  62.  
  63.     private void OnReadProgressChanged(double progress, int bytesRead, int bytesToRead)
  64.     {
  65.         if (ReadProgressChanged != null)
  66.         {
  67.             ReadProgressChanged(this, progress, bytesRead, bytesToRead);
  68.         }
  69.     }
  70.  
  71.     public event WritePacketEventHandler WritePacket;
  72.     public delegate void WritePacketEventHandler(ServerClient sender, int size);
  73.  
  74.     private void OnWritePacket(int size)
  75.     {
  76.         if (WritePacket != null)
  77.         {
  78.             WritePacket(this, size);
  79.         }
  80.     }
  81.  
  82.     public event WriteProgressChangedEventHandler WriteProgressChanged;
  83.     public delegate void WriteProgressChangedEventHandler(ServerClient sender, double progress, int bytesWritten, int bytesToWrite);
  84.  
  85.     private void OnWriteProgressChanged(double progress, int bytesWritten, int bytesToWrite)
  86.     {
  87.         if (WriteProgressChanged != null)
  88.         {
  89.             WriteProgressChanged(this, progress, bytesWritten, bytesToWrite);
  90.         }
  91.     }
  92.  
  93.     #endregion
  94.  
  95.     #region " Properties "
  96.  
  97.     private ushort _BufferSize = 8192;
  98.     public ushort BufferSize
  99.     {
  100.         get { return _BufferSize; }
  101.     }
  102.  
  103.     private int _MaxPacketSize = 10485760;
  104.     public int MaxPacketSize
  105.     {
  106.         get { return _MaxPacketSize; }
  107.         set
  108.         {
  109.             if (value < 1)
  110.             {
  111.                 throw new Exception("Value must be greater than 0.");
  112.             }
  113.             else
  114.             {
  115.                 _MaxPacketSize = value;
  116.             }
  117.         }
  118.     }
  119.  
  120.     private object _UserState;
  121.     public object UserState
  122.     {
  123.         get { return _UserState; }
  124.         set { _UserState = value; }
  125.     }
  126.  
  127.     private IPEndPoint _EndPoint;
  128.     public IPEndPoint EndPoint
  129.     {
  130.         get
  131.         {
  132.             if (_EndPoint != null)
  133.             {
  134.                 return _EndPoint;
  135.             }
  136.             else
  137.             {
  138.                 return new IPEndPoint(IPAddress.None, 0);
  139.             }
  140.         }
  141.     }
  142.  
  143.     private bool _Connected;
  144.     public bool Connected
  145.     {
  146.         get { return _Connected; }
  147.     }
  148.  
  149.     #endregion
  150.  
  151.     private Socket Handle;
  152.  
  153.     private int SendIndex;
  154.     private byte[] SendBuffer;
  155.  
  156.     private int ReadIndex;
  157.     private byte[] ReadBuffer;
  158.  
  159.     private Queue<byte[]> SendQueue;
  160.  
  161.     private bool[] Processing = new bool[2];
  162.     private SocketAsyncEventArgs[] Items = new SocketAsyncEventArgs[2];
  163.  
  164.     public ServerClient(Socket sock, ushort bufferSize, int maxPacketSize)
  165.     {
  166.         try
  167.         {
  168.             Initialize();
  169.             Items[0].SetBuffer(new byte[bufferSize], 0, bufferSize);
  170.  
  171.             Handle = sock;
  172.  
  173.             _BufferSize = bufferSize;
  174.             _MaxPacketSize = maxPacketSize;
  175.             _EndPoint = (IPEndPoint)Handle.RemoteEndPoint;
  176.             _Connected = true;
  177.  
  178.             if (!Handle.ReceiveAsync(Items[0]))
  179.             {
  180.                 Process(null, Items[0]);
  181.             }
  182.         }
  183.         catch (Exception ex)
  184.         {
  185.             OnExceptionThrown(ex);
  186.             Disconnect();
  187.         }
  188.     }
  189.  
  190.     private void Initialize()
  191.     {
  192.         Processing = new bool[2];
  193.  
  194.         SendIndex = 0;
  195.         ReadIndex = 0;
  196.  
  197.         SendBuffer = new byte[-1 + 1];
  198.         ReadBuffer = new byte[-1 + 1];
  199.  
  200.         SendQueue = new Queue<byte[]>();
  201.  
  202.         Items = new SocketAsyncEventArgs[2];
  203.  
  204.         Items[0] = new SocketAsyncEventArgs();
  205.         Items[1] = new SocketAsyncEventArgs();
  206.         Items[0].Completed += Process;
  207.         Items[1].Completed += Process;
  208.     }
  209.  
  210.     private void Process(object s, SocketAsyncEventArgs e)
  211.     {
  212.         try
  213.         {
  214.             if (e.SocketError == SocketError.Success)
  215.             {
  216.                 switch (e.LastOperation)
  217.                 {
  218.                     case SocketAsyncOperation.Receive:
  219.                         if (!_Connected)
  220.                             return;
  221.  
  222.                         if (!(e.BytesTransferred == 0))
  223.                         {
  224.                             HandleRead(e.Buffer, 0, e.BytesTransferred);
  225.  
  226.                             if (!Handle.ReceiveAsync(e))
  227.                             {
  228.                                 Process(null, e);
  229.                             }
  230.                         }
  231.                         else
  232.                         {
  233.                             Disconnect();
  234.                         }
  235.                         break;
  236.                     case SocketAsyncOperation.Send:
  237.                         if (!_Connected)
  238.                             return;
  239.  
  240.                         bool EOS = false;
  241.                         SendIndex += e.BytesTransferred;
  242.  
  243.                         OnWriteProgressChanged((SendIndex / SendBuffer.Length) * 100, SendIndex, SendBuffer.Length);
  244.  
  245.                         if ((SendIndex >= SendBuffer.Length))
  246.                         {
  247.                             EOS = true;
  248.                             OnWritePacket(SendBuffer.Length - 4);
  249.                         }
  250.  
  251.                         if (SendQueue.Count == 0 && EOS)
  252.                         {
  253.                             Processing[1] = false;
  254.                         }
  255.                         else
  256.                         {
  257.                             HandleSendQueue();
  258.                         }
  259.                         break;
  260.                 }
  261.             }
  262.             else
  263.             {
  264.                 OnExceptionThrown(new SocketException(Convert.ToInt32(e.SocketError)));
  265.                 Disconnect();
  266.             }
  267.         }
  268.         catch (Exception ex)
  269.         {
  270.             OnExceptionThrown(ex);
  271.             Disconnect();
  272.         }
  273.     }
  274.  
  275.     public void Disconnect()
  276.     {
  277.         if (Processing[0])
  278.         {
  279.             return;
  280.         }
  281.         else
  282.         {
  283.             Processing[0] = true;
  284.         }
  285.  
  286.         bool Raise = _Connected;
  287.         _Connected = false;
  288.  
  289.         if (Handle != null)
  290.         {
  291.             Handle.Close();
  292.         }
  293.  
  294.         if (SendQueue != null)
  295.         {
  296.             SendQueue.Clear();
  297.         }
  298.  
  299.         SendBuffer = new byte[-1 + 1];
  300.         ReadBuffer = new byte[-1 + 1];
  301.  
  302.         if (Raise)
  303.         {
  304.             OnStateChanged(false);
  305.         }
  306.  
  307.         if (Items != null)
  308.         {
  309.             Items[0].Dispose();
  310.             Items[1].Dispose();
  311.         }
  312.  
  313.         _UserState = null;
  314.         _EndPoint = null;
  315.     }
  316.  
  317.     public void Send(byte[] data)
  318.     {
  319.         if (!_Connected)
  320.             return;
  321.  
  322.         SendQueue.Enqueue(data);
  323.  
  324.         if (!Processing[1])
  325.         {
  326.             Processing[1] = true;
  327.             HandleSendQueue();
  328.         }
  329.     }
  330.  
  331.     private void HandleSendQueue()
  332.     {
  333.         try
  334.         {
  335.             if (SendIndex >= SendBuffer.Length)
  336.             {
  337.                 SendIndex = 0;
  338.                 SendBuffer = Header(SendQueue.Dequeue());
  339.             }
  340.  
  341.             int Write = Math.Min(SendBuffer.Length - SendIndex, _BufferSize);
  342.             Items[1].SetBuffer(SendBuffer, SendIndex, Write);
  343.  
  344.             if (!Handle.SendAsync(Items[1]))
  345.             {
  346.                 Process(null, Items[1]);
  347.             }
  348.         }
  349.         catch (Exception ex)
  350.         {
  351.             OnExceptionThrown(ex);
  352.             Disconnect();
  353.         }
  354.     }
  355.  
  356.     private static byte[] Header(byte[] data)
  357.     {
  358.         byte[] T = new byte[data.Length + 4];
  359.         Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, T, 0, 4);
  360.         Buffer.BlockCopy(data, 0, T, 4, data.Length);
  361.         return T;
  362.     }
  363.  
  364.     private void HandleRead(byte[] data, int index, int length)
  365.     {
  366.         if (ReadIndex >= ReadBuffer.Length)
  367.         {
  368.             ReadIndex = 0;
  369.             if (data.Length < 4)
  370.             {
  371.                 OnExceptionThrown(new Exception("Missing or corrupt packet header."));
  372.                 Disconnect();
  373.                 return;
  374.             }
  375.  
  376.             int PacketSize = BitConverter.ToInt32(data, index);
  377.             if (PacketSize > _MaxPacketSize)
  378.             {
  379.                 OnExceptionThrown(new Exception("Packet size exceeds MaxPacketSize."));
  380.                 Disconnect();
  381.                 return;
  382.             }
  383.  
  384.             Array.Resize(ref ReadBuffer, PacketSize);
  385.             index += 4;
  386.         }
  387.  
  388.         int Read = Math.Min(ReadBuffer.Length - ReadIndex, length - index);
  389.         Buffer.BlockCopy(data, index, ReadBuffer, ReadIndex, Read);
  390.         ReadIndex += Read;
  391.  
  392.         OnReadProgressChanged((ReadIndex / ReadBuffer.Length) * 100, ReadIndex, ReadBuffer.Length);
  393.  
  394.         if (ReadIndex >= ReadBuffer.Length)
  395.         {
  396.             OnReadPacket(ReadBuffer);
  397.         }
  398.  
  399.         if (Read < (length - index))
  400.         {
  401.             HandleRead(data, index + Read, length);
  402.         }
  403.     }
  404.  
  405.     #region " IDisposable Support "
  406.  
  407.     private bool DisposedValue;
  408.  
  409.     private void Dispose(bool disposing)
  410.     {
  411.         if (!DisposedValue && disposing)
  412.             Disconnect();
  413.         DisposedValue = true;
  414.     }
  415.  
  416.     public void Dispose()
  417.     {
  418.         Dispose(true);
  419.         GC.SuppressFinalize(this);
  420.     }
  421.  
  422.     #endregion
  423.  
  424. }
  425.  
  426. sealed class ServerListener : IDisposable
  427. {
  428.  
  429.     //TODO: Remove some redundant code (e.g. Listen and Process socket preparation.)
  430.     //TODO: Stop listening when at connection capacity, as opposed to disconnecting.
  431.     //TODO: Implement option to limit simultaneous connections per source.
  432.  
  433.     #region " Events "
  434.  
  435.     public event StateChangedEventHandler StateChanged;
  436.     public delegate void StateChangedEventHandler(ServerListener sender, bool listening);
  437.  
  438.     private void OnStateChanged(bool listening)
  439.     {
  440.         if (StateChanged != null)
  441.         {
  442.             StateChanged(this, listening);
  443.         }
  444.     }
  445.  
  446.     public event ExceptionThrownEventHandler ExceptionThrown;
  447.     public delegate void ExceptionThrownEventHandler(ServerListener sender, Exception ex);
  448.  
  449.     private void OnExceptionThrown(Exception ex)
  450.     {
  451.         if (ExceptionThrown != null)
  452.         {
  453.             ExceptionThrown(this, ex);
  454.         }
  455.     }
  456.  
  457.     public event ClientExceptionThrownEventHandler ClientExceptionThrown;
  458.     public delegate void ClientExceptionThrownEventHandler(ServerListener sender, ServerClient client, Exception ex);
  459.  
  460.     private void OnClientExceptionThrown(ServerClient client, Exception ex)
  461.     {
  462.         if (ClientExceptionThrown != null)
  463.         {
  464.             ClientExceptionThrown(this, client, ex);
  465.         }
  466.     }
  467.  
  468.     public event ClientStateChangedEventHandler ClientStateChanged;
  469.     public delegate void ClientStateChangedEventHandler(ServerListener sender, ServerClient client, bool connected);
  470.  
  471.     private void OnClientStateChanged(ServerClient client, bool connected)
  472.     {
  473.         if (ClientStateChanged != null)
  474.         {
  475.             ClientStateChanged(this, client, connected);
  476.         }
  477.     }
  478.  
  479.     public event ClientReadPacketEventHandler ClientReadPacket;
  480.     public delegate void ClientReadPacketEventHandler(ServerListener sender, ServerClient client, byte[] data);
  481.  
  482.     private void OnClientReadPacket(ServerClient client, byte[] data)
  483.     {
  484.         if (ClientReadPacket != null)
  485.         {
  486.             ClientReadPacket(this, client, data);
  487.         }
  488.     }
  489.  
  490.     public event ClientReadProgressChangedEventHandler ClientReadProgressChanged;
  491.     public delegate void ClientReadProgressChangedEventHandler(ServerListener sender, ServerClient client, double progress, int bytesRead, int bytesToRead);
  492.  
  493.     private void OnClientReadProgressChanged(ServerClient client, double progress, int bytesRead, int bytesToRead)
  494.     {
  495.         if (ClientReadProgressChanged != null)
  496.         {
  497.             ClientReadProgressChanged(this, client, progress, bytesRead, bytesToRead);
  498.         }
  499.     }
  500.  
  501.     public event ClientWritePacketEventHandler ClientWritePacket;
  502.     public delegate void ClientWritePacketEventHandler(ServerListener sender, ServerClient client, int size);
  503.  
  504.     private void OnClientWritePacket(ServerClient client, int size)
  505.     {
  506.         if (ClientWritePacket != null)
  507.         {
  508.             ClientWritePacket(this, client, size);
  509.         }
  510.     }
  511.  
  512.     public event ClientWriteProgressChangedEventHandler ClientWriteProgressChanged;
  513.     public delegate void ClientWriteProgressChangedEventHandler(ServerListener sender, ServerClient client, double progress, int bytesWritten, int bytesToWrite);
  514.  
  515.     private void OnClientWriteProgressChanged(ServerClient client, double progress, int bytesWritten, int bytesToWrite)
  516.     {
  517.         if (ClientWriteProgressChanged != null)
  518.         {
  519.             ClientWriteProgressChanged(this, client, progress, bytesWritten, bytesToWrite);
  520.         }
  521.     }
  522.  
  523.     #endregion
  524.  
  525.     #region " Properties "
  526.  
  527.     private ushort _BufferSize = 8192;
  528.     public ushort BufferSize
  529.     {
  530.         get { return _BufferSize; }
  531.         set
  532.         {
  533.             if (value < 1)
  534.             {
  535.                 throw new Exception("Value must be greater than 0.");
  536.             }
  537.             else
  538.             {
  539.                 _BufferSize = value;
  540.             }
  541.         }
  542.     }
  543.  
  544.     private int _MaxPacketSize = 10485760;
  545.     public int MaxPacketSize
  546.     {
  547.         get { return _MaxPacketSize; }
  548.         set
  549.         {
  550.             if (value < 1)
  551.             {
  552.                 throw new Exception("Value must be greater than 0.");
  553.             }
  554.             else
  555.             {
  556.                 _MaxPacketSize = value;
  557.             }
  558.         }
  559.     }
  560.  
  561.     private bool _KeepAlive = true;
  562.     public bool KeepAlive
  563.     {
  564.         get { return _KeepAlive; }
  565.         set
  566.         {
  567.             if (_Listening)
  568.             {
  569.                 throw new Exception("Unable to change this option while listening.");
  570.             }
  571.             else
  572.             {
  573.                 _KeepAlive = value;
  574.             }
  575.         }
  576.     }
  577.  
  578.     private ushort _MaxConnections = 20;
  579.     public ushort MaxConnections
  580.     {
  581.         get { return _MaxConnections; }
  582.         set { _MaxConnections = value; }
  583.     }
  584.  
  585.     private bool _Listening;
  586.     public bool Listening
  587.     {
  588.         get { return _Listening; }
  589.     }
  590.  
  591.     private List<ServerClient> _Clients;
  592.     public ServerClient[] Clients
  593.     {
  594.         get {
  595.             if (_Listening) {
  596.                 return _Clients.ToArray();
  597.             } else {
  598.                 return new ServerClient[1];
  599.             }
  600.         }
  601.     }
  602.  
  603.     #endregion
  604.  
  605.     private Socket Handle;
  606.  
  607.     private bool Processing;
  608.     private SocketAsyncEventArgs Item;
  609.  
  610.     public void Listen(ushort port)
  611.     {
  612.         try
  613.         {
  614.             if (!_Listening)
  615.             {
  616.                 _Clients = new List<ServerClient>();
  617.  
  618.                 Item = new SocketAsyncEventArgs();
  619.                 Item.Completed += Process;
  620.                 Item.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  621.                 Item.AcceptSocket.NoDelay = true;
  622.  
  623.                 if (_KeepAlive)
  624.                 {
  625.                     Item.AcceptSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 20000);
  626.                 }
  627.  
  628.                 Handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  629.                 Handle.Bind(new IPEndPoint(IPAddress.Any, port));
  630.                 Handle.Listen(10);
  631.  
  632.                 Processing = false;
  633.                 _Listening = true;
  634.  
  635.                 OnStateChanged(true);
  636.                 if (!Handle.AcceptAsync(Item))
  637.                 {
  638.                     Process(null, Item);
  639.                 }
  640.             }
  641.         }
  642.         catch (Exception ex)
  643.         {
  644.             OnExceptionThrown(ex);
  645.             Disconnect();
  646.         }
  647.     }
  648.  
  649.     private void Process(object s, SocketAsyncEventArgs e)
  650.     {
  651.         try
  652.         {
  653.             if (e.SocketError == SocketError.Success)
  654.             {
  655.                 ServerClient T = new ServerClient(e.AcceptSocket, _BufferSize, _MaxPacketSize);
  656.  
  657.                 lock (_Clients)
  658.                 {
  659.                     if (_Clients.Count < _MaxConnections)
  660.                     {
  661.                         _Clients.Add(T);
  662.                         T.StateChanged += HandleStateChanged;
  663.                         T.ExceptionThrown += OnClientExceptionThrown;
  664.                         T.ReadPacket += OnClientReadPacket;
  665.                         T.ReadProgressChanged += OnClientReadProgressChanged;
  666.                         T.WritePacket += OnClientWritePacket;
  667.                         T.WriteProgressChanged += OnClientWriteProgressChanged;
  668.  
  669.                         OnClientStateChanged(T, true);
  670.                     }
  671.                     else
  672.                     {
  673.                         T.Disconnect();
  674.                     }
  675.                 }
  676.  
  677.                 e.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  678.                 e.AcceptSocket.NoDelay = true;
  679.  
  680.                 if (_KeepAlive)
  681.                 {
  682.                     e.AcceptSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 20000);
  683.                 }
  684.  
  685.                 if (!Handle.AcceptAsync(e))
  686.                 {
  687.                     Process(null, e);
  688.                 }
  689.             }
  690.             else
  691.             {
  692.                 OnExceptionThrown(new SocketException(Convert.ToInt32(e.SocketError)));
  693.                 Disconnect();
  694.             }
  695.         }
  696.         catch (Exception ex)
  697.         {
  698.             OnExceptionThrown(ex);
  699.             Disconnect();
  700.         }
  701.     }
  702.  
  703.     public void Disconnect()
  704.     {
  705.         if (Processing)
  706.         {
  707.             return;
  708.         }
  709.         else
  710.         {
  711.             Processing = true;
  712.         }
  713.  
  714.         if (Handle != null)
  715.         {
  716.             Handle.Close();
  717.         }
  718.  
  719.         lock (_Clients)
  720.         {
  721.             while (_Clients.Count > 0)
  722.             {
  723.                 _Clients[0].Disconnect();
  724.                 _Clients.RemoveAt(0);
  725.             }
  726.         }
  727.  
  728.         if (Item != null)
  729.         {
  730.             Item.Dispose();
  731.         }
  732.  
  733.         _Listening = false;
  734.         OnStateChanged(false);
  735.     }
  736.  
  737.     private void HandleStateChanged(ServerClient client, bool connected)
  738.     {
  739.         lock (_Clients)
  740.         {
  741.             _Clients.Remove(client);
  742.             OnClientStateChanged(client, false);
  743.         }
  744.     }
  745.  
  746.     #region " IDisposable Support "
  747.  
  748.     private bool DisposedValue;
  749.  
  750.     private void Dispose(bool disposing)
  751.     {
  752.         if (!DisposedValue && disposing)
  753.             Disconnect();
  754.         DisposedValue = true;
  755.     }
  756.  
  757.     public void Dispose()
  758.     {
  759.         Dispose(true);
  760.         GC.SuppressFinalize(this);
  761.     }
  762.  
  763.     #endregion
  764.  
  765. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement