diff --git a/Articulate-Network.csproj b/Articulate-Network.csproj index cbf6406..abf17fc 100644 --- a/Articulate-Network.csproj +++ b/Articulate-Network.csproj @@ -44,9 +44,11 @@ + + diff --git a/Client.cs b/Client.cs index 9c0f576..2c875a3 100644 --- a/Client.cs +++ b/Client.cs @@ -1,9 +1,14 @@ using Articulate_Network.Interfaces; +using Articulate_Network.Managers; +using Articulate_Network.Packets; using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; +using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -12,12 +17,19 @@ namespace Articulate_Network public class Client { List managers = new List(); + int bufferSize = 16384; TcpClient tcp; public Client() { - tcp = new TcpClient(); + InitializeManagers(); + + tcp = new TcpClient() + { + SendBufferSize = bufferSize, + ReceiveBufferSize = bufferSize + }; } public async Task Connect(string ip, int port) @@ -28,6 +40,11 @@ namespace Articulate_Network { tcp.Connect(ip, port); + tcp.SendBufferSize = bufferSize; + tcp.ReceiveBufferSize = bufferSize; + + _ = ReceiveData(); + return tcp; } catch (Exception e) @@ -39,9 +56,121 @@ namespace Articulate_Network ); } - public async Task SendPacket(IPacket packet) + public async Task SendPacket(Packet packet) { + await Task.Run(() => + { + byte[] buffer = Get().SerializePacket(packet); + + tcp.Client.Send(buffer, buffer.Length, SocketFlags.None); + }); + return false; } + + public async Task ReceiveData() + { + await Task.Run(() => + { + byte[] buffer = new byte[bufferSize]; + + int offset = 0; + + while (true) + { + int bytesToRead = tcp.Client.Receive(buffer, offset, buffer.Length - offset, SocketFlags.None); + + //Console.WriteLine("Bytes to read: " + bytesToRead); + + var ms = new MemoryStream(buffer, 0, bytesToRead); + var br = new BinaryReader(ms); + + while (ms.Position < ms.Length) + { + int length = (int)br.ReadInt64(); + + OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs() + { + Packet = Get().DeserializePacket(ms) + }); + + int end = (int)br.ReadInt64(); + + bool endOfPacket = end == length; + + if (endOfPacket && ms.Position < ms.Length) + { + int nextPacketSize = (int)br.ReadInt64(); + + ms.Position -= 8; + + Console.WriteLine("Next size: " + nextPacketSize); + + offset = (int)(ms.Length - ms.Position); + + buffer = new byte[bufferSize]; + + ms.Read(buffer, 0, offset); + + break; + } + + //Console.WriteLine(ms.Position); + + /*if (ms.Position + length > ms.Length) + { + Console.WriteLine("Bytes to read: " + bytesToRead); + Console.WriteLine("Memory length: " + ms.Length); + Console.WriteLine("Memory Pos: " + ms.Position); + Console.WriteLine("Length: " + length); + ms.Position -= 8; + + buffer = new byte[bufferSize]; + + ms.Read(buffer, 0, offset); + break; + }*/ + } + } + }); + + return false; + } + + public void InitializeManagers() + { + var @interface = typeof(IManager); + + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + var managersFound = assembly.GetTypes().Where(t => @interface.IsAssignableFrom(t) && !t.IsAbstract); + + foreach (var m in managersFound) + { + var manager = (IManager)Activator.CreateInstance(m); + + manager.Initialize(); + + managers.Add(manager); + } + } + + Console.WriteLine($"Initialized {managers.Count} manager{(managers.Count > 1 ? "s" : "")}"); + } + + public T Get() + { + return (T)managers.SingleOrDefault(t => typeof(T) == t.GetType()); + } + + protected virtual void OnDataReceived(Articulate_Network.Events.DataReceivedEventArgs e) + { + EventHandler handler = DataReceived; + + if (handler != null) + handler(this, e); + } + + public event EventHandler DataReceived; } } diff --git a/Managers/PacketManager.cs b/Managers/PacketManager.cs index 3aa3158..3f69161 100644 --- a/Managers/PacketManager.cs +++ b/Managers/PacketManager.cs @@ -1,5 +1,6 @@ using Articulate_Network.Attributes; using Articulate_Network.Interfaces; +using Articulate_Network.Packets; using System; using System.Collections.Generic; using System.Diagnostics; @@ -14,7 +15,7 @@ namespace Articulate_Network.Managers public class PacketManager : IManager { Dictionary> packetInfo = new Dictionary>(); - Dictionary packetInstances = new Dictionary(); + Dictionary packetInstances = new Dictionary(); public void Initialize() { @@ -22,13 +23,13 @@ namespace Articulate_Network.Managers foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { - var managersFound = assembly.GetTypes().Where(t => @interface.IsAssignableFrom(t) && !t.IsAbstract); + var packetsFound = assembly.GetTypes().Where(t => @interface.IsAssignableFrom(t) && !t.IsAbstract); - foreach (var p in managersFound) + foreach (var p in packetsFound) { - var packet = (IPacket)Activator.CreateInstance(p); + var packet = (Packet)Activator.CreateInstance(p); - packetInstances.Add(p, packet); + packetInstances.Add(p.Name, packet); LoadPacketInfo(packet); } } @@ -41,7 +42,7 @@ namespace Articulate_Network.Managers packetInfo.Add(packet.GetType(), packet.GetType().GetProperties().Where(f => !Attribute.IsDefined(f, typeof(PacketIgnore))).OrderBy(f => f.Name).ToList()); } - public T Send(IPacket packet) + public void Send(Packet packet) { Stopwatch watch = new Stopwatch(); watch.Start(); @@ -57,19 +58,24 @@ namespace Articulate_Network.Managers var serialized = SerializePacket(packet); - var deserialized = DeserializePacket(serialized); + //var deserialized = DeserializePacket(serialized); - return (T)deserialized; + //return (T)deserialized; } - public MemoryStream SerializePacket(IPacket packet) + public byte[] SerializePacket(Packet packet) { + if (!packetInfo.ContainsKey(packet.GetType())) + LoadPacketInfo(packet); + Stopwatch watch = new Stopwatch(); watch.Start(); var fields = packetInfo[packet.GetType()]; - MemoryStream memoryStream = new MemoryStream(); - BinaryWriter binaryWriter = new BinaryWriter(memoryStream); + MemoryStream buffer = new MemoryStream(); + BinaryWriter binaryWriter = new BinaryWriter(buffer); + + binaryWriter.Write(packet.GetType().Name); foreach (var field in fields) { @@ -79,27 +85,57 @@ namespace Articulate_Network.Managers if (field.PropertyType == typeof(int)) binaryWriter.Write((int)field.GetValue(packet)); + if (field.PropertyType == typeof(long)) + binaryWriter.Write((long)field.GetValue(packet)); + if (field.PropertyType == typeof(string)) - binaryWriter.Write((string)field.GetValue(packet)); + binaryWriter.Write(((string)field.GetValue(packet)) ?? string.Empty); + + if (field.PropertyType.IsEnum) + binaryWriter.Write((int)field.GetValue(packet)); + + if (field.PropertyType == typeof(byte[])) + { + byte[] buf = (byte[])field.GetValue(packet); + binaryWriter.Write(buf.Length); + binaryWriter.Write(buf); + } + + //Console.WriteLine(field.Name); } - memoryStream.Position = 0; + long length = buffer.Length; + byte[] packetData = buffer.ToArray(); + + buffer.SetLength(0); + + binaryWriter.Write(length); + binaryWriter.Write(packetData); + binaryWriter.Write(length); watch.Stop(); - Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds"); - return memoryStream; + //Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds"); + return buffer.ToArray(); } - public T DeserializePacket(Stream stream) + public Packet DeserializePacket(MemoryStream stream) { Stopwatch watch = new Stopwatch(); watch.Start(); - IPacket packet = /*packetInstances[typeof(T)];*/(IPacket)Activator.CreateInstance(typeof(T)); - - var fields = packetInfo[typeof(T)]; BinaryReader reader = new BinaryReader(stream); + string typeName = reader.ReadString(); + + Console.WriteLine(typeName); + + Packet packet = packetInstances[typeName];/*(IPacket)Activator.CreateInstance(typeof(T));*/ + + var fields = packetInfo[packet.GetType()]; + + //Console.WriteLine($"Stream length: {stream.Length}"); + //Console.WriteLine($"Stream position: {stream.Position}"); + foreach (var field in fields) { if (field.PropertyType == typeof(bool)) @@ -108,15 +144,37 @@ namespace Articulate_Network.Managers if (field.PropertyType == typeof(int)) field.SetValue(packet, reader.ReadInt32()); + if (field.PropertyType == typeof(long)) + field.SetValue(packet, reader.ReadInt64()); + if (field.PropertyType == typeof(string)) field.SetValue(packet, reader.ReadString()); + + if (field.PropertyType.IsEnum) + field.SetValue(packet, reader.ReadInt32()); + + if (field.PropertyType == typeof(byte[])) + { + int length = reader.ReadInt32(); + field.SetValue(packet, reader.ReadBytes(length)); + } } watch.Stop(); - Console.WriteLine($"Deserialize time: {watch.ElapsedTicks / 10} microseconds"); + //Console.WriteLine($"Deserialize time: {watch.ElapsedTicks / 10} microseconds"); - return (T)packet; + return packet; + } + + public Packet DeserializePacket(byte[] bytes) + { + return DeserializePacket(new MemoryStream(bytes)); + } + + public void HandlePacket(Packet packet) + { + Console.WriteLine(packet.GetType().Name); } } } diff --git a/Packets/Packet.cs b/Packets/Packet.cs new file mode 100644 index 0000000..71a76c8 --- /dev/null +++ b/Packets/Packet.cs @@ -0,0 +1,14 @@ +using Articulate_Network.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Articulate_Network.Packets +{ + public abstract class Packet : IPacket + { + + } +} diff --git a/Server.cs b/Server.cs index f53f4c3..17309cc 100644 --- a/Server.cs +++ b/Server.cs @@ -1,8 +1,10 @@ using Articulate_Network.Events; using Articulate_Network.Interfaces; using Articulate_Network.Managers; +using Articulate_Network.Packets; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; @@ -15,15 +17,13 @@ namespace Articulate_Network public class Server { List managers = new List(); - List clients = new List(); + TcpClient[] clients = new TcpClient[300]; TcpListener tcpListener; public Server() { InitializeManagers(); - - Console.WriteLine($"Initialized {managers.Count} manager{(managers.Count > 1 ? "s" : "")}"); } public async Task Start(string ip, int port) @@ -57,16 +57,74 @@ namespace Articulate_Network { var client = await tcpListener.AcceptTcpClientAsync(); - clients.Add(client); + for (int i = 0; i < clients.Length; i++) + if (clients[i] == null) + { + clients[i] = client; + Console.WriteLine($"Client {i+1} connected from {(client.Client.RemoteEndPoint as IPEndPoint).Address}."); + break; + } + + _ = ReceiveData(client); OnClientConnected(new ClientConnectedEventArgs() { TcpClient = client }); } } - - - public async Task SendPacket(IPacket packet) + public async Task ReceiveData(TcpClient client) { + await Task.Run(() => + { + byte[] buffer = new byte[8192]; + var ms = new MemoryStream(buffer); + var br = new BinaryReader(ms); + + while (client.Connected) + { + try + { + int bytesToRead = client.Client.Receive(buffer, buffer.Length, SocketFlags.None); + + ms.Position = 0; + + while (ms.Position < bytesToRead) + { + int length = (int)br.ReadInt64(); + + OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs() + { + Packet = Get().DeserializePacket(ms), + Client = client + }); + + int end = (int)br.ReadInt64(); + } + } + catch (SocketException e) + { + for (int i = 0; i < clients.Length; i++) + if (clients[i] == client) + { + clients[i] = null; + Console.WriteLine($"Client {i+1} lost connection."); + break; + } + } + } + }); + + return false; + } + + public async Task SendPacket(TcpClient tcpClient, Packet packet) + { + await Task.Run(() => + { + byte[] buffer = Get().SerializePacket(packet); + + tcpClient.Client.Send(buffer, buffer.Length, SocketFlags.None); + }); + return false; } @@ -87,6 +145,8 @@ namespace Articulate_Network managers.Add(manager); } } + + Console.WriteLine($"Initialized {managers.Count} manager{(managers.Count > 1 ? "s" : "")}"); } public T Get() @@ -103,5 +163,15 @@ namespace Articulate_Network } public event EventHandler ClientConnected; + + protected virtual void OnDataReceived(Articulate_Network.Events.DataReceivedEventArgs e) + { + EventHandler handler = DataReceived; + + if (handler != null) + handler(this, e); + } + + public event EventHandler DataReceived; } }