Compare commits

...

2 Commits

Author SHA1 Message Date
a9bc8c4e7d Created and implemented Packet abstract class 2021-12-15 15:17:00 +10:00
cdda6c0c8a Start on Server & Client Events
Created ClientConnected event
Created DataReceived event
2021-12-15 15:14:05 +10:00
8 changed files with 321 additions and 32 deletions

View File

@ -44,9 +44,11 @@
<Compile Include="Attributes\PacketIgnore.cs" /> <Compile Include="Attributes\PacketIgnore.cs" />
<Compile Include="Client.cs" /> <Compile Include="Client.cs" />
<Compile Include="Events\ClientConnectedEventArgs.cs" /> <Compile Include="Events\ClientConnectedEventArgs.cs" />
<Compile Include="Events\DataReceivedEventArgs.cs" />
<Compile Include="Interfaces\IManager.cs" /> <Compile Include="Interfaces\IManager.cs" />
<Compile Include="Interfaces\IPacket.cs" /> <Compile Include="Interfaces\IPacket.cs" />
<Compile Include="Managers\PacketManager.cs" /> <Compile Include="Managers\PacketManager.cs" />
<Compile Include="Packets\Packet.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server.cs" /> <Compile Include="Server.cs" />
</ItemGroup> </ItemGroup>

View File

@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace Articulate_Network.Attributes namespace Articulate_Network.Attributes
{ {
public class PacketIgnore : System.Attribute public class PacketIgnore : Attribute
{ {
} }

133
Client.cs
View File

@ -1,9 +1,14 @@
using Articulate_Network.Interfaces; using Articulate_Network.Interfaces;
using Articulate_Network.Managers;
using Articulate_Network.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,12 +17,19 @@ namespace Articulate_Network
public class Client public class Client
{ {
List<IManager> managers = new List<IManager>(); List<IManager> managers = new List<IManager>();
int bufferSize = 16384;
TcpClient tcp; TcpClient tcp;
public Client() public Client()
{ {
tcp = new TcpClient(); InitializeManagers();
tcp = new TcpClient()
{
SendBufferSize = bufferSize,
ReceiveBufferSize = bufferSize
};
} }
public async Task<TcpClient> Connect(string ip, int port) public async Task<TcpClient> Connect(string ip, int port)
@ -28,6 +40,11 @@ namespace Articulate_Network
{ {
tcp.Connect(ip, port); tcp.Connect(ip, port);
tcp.SendBufferSize = bufferSize;
tcp.ReceiveBufferSize = bufferSize;
_ = ReceiveData();
return tcp; return tcp;
} }
catch (Exception e) catch (Exception e)
@ -39,9 +56,121 @@ namespace Articulate_Network
); );
} }
public async Task<bool> SendPacket(IPacket packet) public async Task<bool> SendPacket(Packet packet)
{ {
await Task.Run(() =>
{
byte[] buffer = Get<PacketManager>().SerializePacket(packet);
tcp.Client.Send(buffer, buffer.Length, SocketFlags.None);
});
return false; return false;
} }
public async Task<bool> 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<PacketManager>().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<T>()
{
return (T)managers.SingleOrDefault(t => typeof(T) == t.GetType());
}
protected virtual void OnDataReceived(Articulate_Network.Events.DataReceivedEventArgs e)
{
EventHandler<Articulate_Network.Events.DataReceivedEventArgs> handler = DataReceived;
if (handler != null)
handler(this, e);
}
public event EventHandler<Articulate_Network.Events.DataReceivedEventArgs> DataReceived;
} }
} }

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace Articulate_Network.Events namespace Articulate_Network.Events
{ {
public class ClientConnectedEventArgs public class ClientConnectedEventArgs : EventArgs
{ {
public TcpClient TcpClient { get; set; } public TcpClient TcpClient { get; set; }
} }

View File

@ -0,0 +1,16 @@
using Articulate_Network.Packets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Articulate_Network.Events
{
public class DataReceivedEventArgs : EventArgs
{
public TcpClient Client { get; set; }
public Packet Packet { get; set; }
}
}

View File

@ -1,5 +1,6 @@
using Articulate_Network.Attributes; using Articulate_Network.Attributes;
using Articulate_Network.Interfaces; using Articulate_Network.Interfaces;
using Articulate_Network.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -14,7 +15,7 @@ namespace Articulate_Network.Managers
public class PacketManager : IManager public class PacketManager : IManager
{ {
Dictionary<Type, List<PropertyInfo>> packetInfo = new Dictionary<Type, List<PropertyInfo>>(); Dictionary<Type, List<PropertyInfo>> packetInfo = new Dictionary<Type, List<PropertyInfo>>();
Dictionary<Type, IPacket> packetInstances = new Dictionary<Type, IPacket>(); Dictionary<string, Packet> packetInstances = new Dictionary<string, Packet>();
public void Initialize() public void Initialize()
{ {
@ -22,13 +23,13 @@ namespace Articulate_Network.Managers
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 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); 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()); packetInfo.Add(packet.GetType(), packet.GetType().GetProperties().Where(f => !Attribute.IsDefined(f, typeof(PacketIgnore))).OrderBy(f => f.Name).ToList());
} }
public T Send<T>(IPacket packet) public void Send(Packet packet)
{ {
Stopwatch watch = new Stopwatch(); Stopwatch watch = new Stopwatch();
watch.Start(); watch.Start();
@ -57,19 +58,24 @@ namespace Articulate_Network.Managers
var serialized = SerializePacket(packet); var serialized = SerializePacket(packet);
var deserialized = DeserializePacket<T>(serialized); //var deserialized = DeserializePacket<T>(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(); Stopwatch watch = new Stopwatch();
watch.Start(); watch.Start();
var fields = packetInfo[packet.GetType()]; var fields = packetInfo[packet.GetType()];
MemoryStream memoryStream = new MemoryStream(); MemoryStream buffer = new MemoryStream();
BinaryWriter binaryWriter = new BinaryWriter(memoryStream); BinaryWriter binaryWriter = new BinaryWriter(buffer);
binaryWriter.Write(packet.GetType().Name);
foreach (var field in fields) foreach (var field in fields)
{ {
@ -79,27 +85,57 @@ namespace Articulate_Network.Managers
if (field.PropertyType == typeof(int)) if (field.PropertyType == typeof(int))
binaryWriter.Write((int)field.GetValue(packet)); binaryWriter.Write((int)field.GetValue(packet));
if (field.PropertyType == typeof(long))
binaryWriter.Write((long)field.GetValue(packet));
if (field.PropertyType == typeof(string)) 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(); watch.Stop();
Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds"); //Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds");
return memoryStream; return buffer.ToArray();
} }
public T DeserializePacket<T>(Stream stream) public Packet DeserializePacket(MemoryStream stream)
{ {
Stopwatch watch = new Stopwatch(); Stopwatch watch = new Stopwatch();
watch.Start(); watch.Start();
IPacket packet = /*packetInstances[typeof(T)];*/(IPacket)Activator.CreateInstance(typeof(T));
var fields = packetInfo[typeof(T)];
BinaryReader reader = new BinaryReader(stream); 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) foreach (var field in fields)
{ {
if (field.PropertyType == typeof(bool)) if (field.PropertyType == typeof(bool))
@ -108,15 +144,37 @@ namespace Articulate_Network.Managers
if (field.PropertyType == typeof(int)) if (field.PropertyType == typeof(int))
field.SetValue(packet, reader.ReadInt32()); field.SetValue(packet, reader.ReadInt32());
if (field.PropertyType == typeof(long))
field.SetValue(packet, reader.ReadInt64());
if (field.PropertyType == typeof(string)) if (field.PropertyType == typeof(string))
field.SetValue(packet, reader.ReadString()); 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(); 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);
} }
} }
} }

14
Packets/Packet.cs Normal file
View File

@ -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
{
}
}

View File

@ -1,8 +1,10 @@
using Articulate_Network.Events; using Articulate_Network.Events;
using Articulate_Network.Interfaces; using Articulate_Network.Interfaces;
using Articulate_Network.Managers; using Articulate_Network.Managers;
using Articulate_Network.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@ -15,15 +17,13 @@ namespace Articulate_Network
public class Server public class Server
{ {
List<IManager> managers = new List<IManager>(); List<IManager> managers = new List<IManager>();
List<TcpClient> clients = new List<TcpClient>(); TcpClient[] clients = new TcpClient[300];
TcpListener tcpListener; TcpListener tcpListener;
public Server() public Server()
{ {
InitializeManagers(); InitializeManagers();
Console.WriteLine($"Initialized {managers.Count} manager{(managers.Count > 1 ? "s" : "")}");
} }
public async Task<bool> Start(string ip, int port) public async Task<bool> Start(string ip, int port)
@ -57,16 +57,74 @@ namespace Articulate_Network
{ {
var client = await tcpListener.AcceptTcpClientAsync(); 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 }); OnClientConnected(new ClientConnectedEventArgs() { TcpClient = client });
} }
} }
public async Task<bool> ReceiveData(TcpClient client)
public async Task<bool> SendPacket(IPacket packet)
{ {
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<PacketManager>().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<bool> SendPacket(TcpClient tcpClient, Packet packet)
{
await Task.Run(() =>
{
byte[] buffer = Get<PacketManager>().SerializePacket(packet);
tcpClient.Client.Send(buffer, buffer.Length, SocketFlags.None);
});
return false; return false;
} }
@ -87,6 +145,8 @@ namespace Articulate_Network
managers.Add(manager); managers.Add(manager);
} }
} }
Console.WriteLine($"Initialized {managers.Count} manager{(managers.Count > 1 ? "s" : "")}");
} }
public T Get<T>() public T Get<T>()
@ -103,5 +163,15 @@ namespace Articulate_Network
} }
public event EventHandler<ClientConnectedEventArgs> ClientConnected; public event EventHandler<ClientConnectedEventArgs> ClientConnected;
protected virtual void OnDataReceived(Articulate_Network.Events.DataReceivedEventArgs e)
{
EventHandler<Articulate_Network.Events.DataReceivedEventArgs> handler = DataReceived;
if (handler != null)
handler(this, e);
}
public event EventHandler<Articulate_Network.Events.DataReceivedEventArgs> DataReceived;
} }
} }