Compare commits
7 Commits
27978346ae
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ece0dffd85 | |||
| a9bc8c4e7d | |||
| cdda6c0c8a | |||
| fc1195c446 | |||
| 87a569ee9e | |||
| 2e9a712e71 | |||
| 46405a8cf4 |
59
Articulate-Network.csproj
Normal file
59
Articulate-Network.csproj
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{36A8EC7B-B239-4744-892A-4FE633511E8D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Articulate_Network</RootNamespace>
|
||||
<AssemblyName>Articulate-Network</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Attributes\PacketIgnore.cs" />
|
||||
<Compile Include="Client.cs" />
|
||||
<Compile Include="Events\ClientConnectedEventArgs.cs" />
|
||||
<Compile Include="Events\DataReceivedEventArgs.cs" />
|
||||
<Compile Include="Interfaces\IManager.cs" />
|
||||
<Compile Include="Interfaces\IPacket.cs" />
|
||||
<Compile Include="Managers\PacketManager.cs" />
|
||||
<Compile Include="Packets\Packet.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Server.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Enums\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
25
Articulate-Network.sln
Normal file
25
Articulate-Network.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31624.102
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Articulate-Network", "Articulate-Network.csproj", "{36A8EC7B-B239-4744-892A-4FE633511E8D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{36A8EC7B-B239-4744-892A-4FE633511E8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{36A8EC7B-B239-4744-892A-4FE633511E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{36A8EC7B-B239-4744-892A-4FE633511E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{36A8EC7B-B239-4744-892A-4FE633511E8D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {81DCC61E-0253-4356-8FBF-8DF05F4B7FA1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
13
Attributes/PacketIgnore.cs
Normal file
13
Attributes/PacketIgnore.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Articulate_Network.Attributes
|
||||
{
|
||||
public class PacketIgnore : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
180
Client.cs
Normal file
180
Client.cs
Normal file
@ -0,0 +1,180 @@
|
||||
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;
|
||||
|
||||
namespace Articulate_Network
|
||||
{
|
||||
public class Client
|
||||
{
|
||||
List<IManager> managers = new List<IManager>();
|
||||
int bufferSize = 16384;
|
||||
|
||||
TcpClient tcp;
|
||||
|
||||
public Client()
|
||||
{
|
||||
InitializeManagers();
|
||||
|
||||
tcp = new TcpClient()
|
||||
{
|
||||
SendBufferSize = bufferSize,
|
||||
ReceiveBufferSize = bufferSize
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<TcpClient> Connect(string ip, int port)
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
tcp.Connect(ip, port);
|
||||
|
||||
tcp.SendBufferSize = bufferSize;
|
||||
tcp.ReceiveBufferSize = bufferSize;
|
||||
|
||||
_ = ReceiveData();
|
||||
|
||||
return tcp;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
return tcp;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (offset > 0)
|
||||
offset = 0;
|
||||
|
||||
var ms = new MemoryStream(buffer);
|
||||
var br = new BinaryReader(ms);
|
||||
|
||||
while (ms.Position < ms.Length)
|
||||
{
|
||||
if (ms.Position + 4 > ms.Length)
|
||||
break;
|
||||
|
||||
int magic = br.ReadInt32();
|
||||
|
||||
if (magic != 6655)
|
||||
{
|
||||
//Console.WriteLine("Not the start of a packet.");
|
||||
continue;
|
||||
}
|
||||
|
||||
int length = (int)br.ReadInt64();
|
||||
|
||||
if (ms.Position + length > ms.Length) // Received partial packet data, store partial data and continue
|
||||
{
|
||||
ms.Position -= 12;
|
||||
|
||||
offset = (int)(ms.Length - ms.Position);
|
||||
|
||||
//Console.WriteLine($"Partial data. Offset: {offset}");
|
||||
|
||||
buffer = new byte[bufferSize];
|
||||
|
||||
ms.Read(buffer, 0, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
ms.Position += length;
|
||||
|
||||
int end = (int)br.ReadInt64();
|
||||
|
||||
ms.Position -= 8;
|
||||
ms.Position -= length;
|
||||
|
||||
if (length == end && length > 1) // Valid packet, trigger event
|
||||
{
|
||||
var p = Get<PacketManager>().DeserializePacket(ms);
|
||||
|
||||
OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs()
|
||||
{
|
||||
Packet = p
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Not a valid packet. Length: {length} - End: {end} - Offset: {offset} - Position: {ms.Position}");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
15
Events/ClientConnectedEventArgs.cs
Normal file
15
Events/ClientConnectedEventArgs.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Articulate_Network.Events
|
||||
{
|
||||
public class ClientConnectedEventArgs : EventArgs
|
||||
{
|
||||
public TcpClient TcpClient { get; set; }
|
||||
}
|
||||
}
|
||||
16
Events/DataReceivedEventArgs.cs
Normal file
16
Events/DataReceivedEventArgs.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
13
Interfaces/IManager.cs
Normal file
13
Interfaces/IManager.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Articulate_Network.Interfaces
|
||||
{
|
||||
public interface IManager
|
||||
{
|
||||
void Initialize();
|
||||
}
|
||||
}
|
||||
13
Interfaces/IPacket.cs
Normal file
13
Interfaces/IPacket.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Articulate_Network.Interfaces
|
||||
{
|
||||
public interface IPacket
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
185
Managers/PacketManager.cs
Normal file
185
Managers/PacketManager.cs
Normal file
@ -0,0 +1,185 @@
|
||||
using Articulate_Network.Attributes;
|
||||
using Articulate_Network.Interfaces;
|
||||
using Articulate_Network.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Articulate_Network.Managers
|
||||
{
|
||||
public class PacketManager : IManager
|
||||
{
|
||||
Dictionary<Type, List<PropertyInfo>> packetInfo = new Dictionary<Type, List<PropertyInfo>>();
|
||||
Dictionary<string, Packet> packetInstances = new Dictionary<string, Packet>();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var @interface = typeof(IPacket);
|
||||
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
var packetsFound = assembly.GetTypes().Where(t => @interface.IsAssignableFrom(t) && !t.IsAbstract);
|
||||
|
||||
foreach (var p in packetsFound)
|
||||
{
|
||||
var packet = (Packet)Activator.CreateInstance(p);
|
||||
|
||||
packetInstances.Add(p.Name, packet);
|
||||
LoadPacketInfo(packet);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Registered {packetInstances.Count} packet{(packetInstances.Count == 1 ? "" : "s")}");
|
||||
}
|
||||
|
||||
public void LoadPacketInfo(IPacket packet)
|
||||
{
|
||||
packetInfo.Add(packet.GetType(), packet.GetType().GetProperties().Where(f => !Attribute.IsDefined(f, typeof(PacketIgnore))).OrderBy(f => f.Name).ToList());
|
||||
}
|
||||
|
||||
public void Send(Packet packet)
|
||||
{
|
||||
Stopwatch watch = new Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
if (!packetInfo.ContainsKey(packet.GetType()))
|
||||
LoadPacketInfo(packet);
|
||||
|
||||
watch.Stop();
|
||||
|
||||
Console.WriteLine($"Reflection time: {watch.ElapsedTicks / 10} microseconds");
|
||||
|
||||
//send packet
|
||||
|
||||
var serialized = SerializePacket(packet);
|
||||
|
||||
//var deserialized = DeserializePacket<T>(serialized);
|
||||
|
||||
//return (T)deserialized;
|
||||
}
|
||||
|
||||
public byte[] SerializePacket(Packet packet)
|
||||
{
|
||||
if (!packetInfo.ContainsKey(packet.GetType()))
|
||||
LoadPacketInfo(packet);
|
||||
|
||||
Stopwatch watch = new Stopwatch();
|
||||
watch.Start();
|
||||
var fields = packetInfo[packet.GetType()];
|
||||
|
||||
MemoryStream buffer = new MemoryStream();
|
||||
BinaryWriter binaryWriter = new BinaryWriter(buffer);
|
||||
|
||||
binaryWriter.Write(packet.GetType().Name);
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (field.PropertyType == typeof(bool))
|
||||
binaryWriter.Write((bool)field.GetValue(packet));
|
||||
|
||||
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)) ?? 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);
|
||||
}
|
||||
|
||||
byte[] packetData = buffer.ToArray();
|
||||
long length = packetData.Length;
|
||||
|
||||
buffer.SetLength(0);
|
||||
|
||||
binaryWriter.Write(6655);
|
||||
binaryWriter.Write(length);
|
||||
binaryWriter.Write(packetData);
|
||||
binaryWriter.Write(length);
|
||||
|
||||
//Console.WriteLine("Sent bytes: " + length);
|
||||
|
||||
watch.Stop();
|
||||
|
||||
//Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds");
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
public Packet DeserializePacket(MemoryStream stream)
|
||||
{
|
||||
Stopwatch watch = new Stopwatch();
|
||||
watch.Start();
|
||||
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))
|
||||
field.SetValue(packet, reader.ReadBoolean());
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
reader.ReadInt64();
|
||||
|
||||
watch.Stop();
|
||||
|
||||
//Console.WriteLine($"Deserialize time: {watch.ElapsedTicks / 10} microseconds");
|
||||
|
||||
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
14
Packets/Packet.cs
Normal 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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
36
Properties/AssemblyInfo.cs
Normal file
36
Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Articulate-Network")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Queensland Government")]
|
||||
[assembly: AssemblyProduct("Articulate-Network")]
|
||||
[assembly: AssemblyCopyright("Copyright © Queensland Government 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("36a8ec7b-b239-4744-892a-4fe633511e8d")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
250
Server.cs
Normal file
250
Server.cs
Normal file
@ -0,0 +1,250 @@
|
||||
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;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Articulate_Network
|
||||
{
|
||||
public class Server
|
||||
{
|
||||
List<IManager> managers = new List<IManager>();
|
||||
TcpClient[] clients = new TcpClient[300];
|
||||
|
||||
TcpListener tcpListener;
|
||||
|
||||
public Server()
|
||||
{
|
||||
InitializeManagers();
|
||||
}
|
||||
|
||||
public async Task<bool> Start(string ip, int port)
|
||||
{
|
||||
tcpListener = new TcpListener(IPAddress.Parse(ip), port);
|
||||
|
||||
bool connected = await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
tcpListener.Start();
|
||||
|
||||
_ = HandleConnections();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task HandleConnections()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var client = await tcpListener.AcceptTcpClientAsync();
|
||||
|
||||
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<bool> 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<PacketManager>().DeserializePacket(ms),
|
||||
Client = client
|
||||
});
|
||||
|
||||
int end = (int)br.ReadInt64();
|
||||
}
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}*/
|
||||
|
||||
public async Task<bool> ReceiveData(TcpClient client)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
byte[] buffer = new byte[16384];
|
||||
int offset = 0;
|
||||
|
||||
while (client.Connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
int bytesToRead = client.Client.Receive(buffer, offset, buffer.Length - offset, SocketFlags.None);
|
||||
|
||||
if (bytesToRead == 0)
|
||||
{
|
||||
Console.WriteLine("No data.");
|
||||
continue;
|
||||
}
|
||||
|
||||
var ms = new MemoryStream(buffer);
|
||||
var br = new BinaryReader(ms);
|
||||
|
||||
if (offset > 0)
|
||||
offset = 0;
|
||||
|
||||
while (ms.Position < ms.Length)
|
||||
{
|
||||
br.ReadInt32();
|
||||
int length = (int)br.ReadInt64();
|
||||
if (length < 0)
|
||||
break;
|
||||
|
||||
if (ms.Position + length > ms.Length)
|
||||
{
|
||||
ms.Position -= 8;
|
||||
|
||||
buffer = new byte[16384];
|
||||
|
||||
offset = (int)(ms.Length - ms.Position);
|
||||
|
||||
ms.Read(buffer, 0, offset);
|
||||
|
||||
break;
|
||||
}
|
||||
ms.Position += length;
|
||||
|
||||
int end = (int)br.ReadInt64();
|
||||
|
||||
ms.Position -= 8;
|
||||
|
||||
if (length == end && length < 1)
|
||||
break;
|
||||
|
||||
ms.Position -= length;
|
||||
|
||||
var p = Get<PacketManager>().DeserializePacket(ms);
|
||||
|
||||
OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs()
|
||||
{
|
||||
Packet = p,
|
||||
Client = client
|
||||
});
|
||||
|
||||
br.ReadInt64();
|
||||
}
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
Console.WriteLine("Client disconnected.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> SendPacket(TcpClient tcpClient, Packet packet)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
byte[] buffer = Get<PacketManager>().SerializePacket(packet);
|
||||
|
||||
int sentBytes = tcpClient.Client.Send(buffer, buffer.Length, SocketFlags.None);
|
||||
|
||||
if (sentBytes == 0)
|
||||
Console.WriteLine($"Sent: {sentBytes}");
|
||||
});
|
||||
|
||||
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 OnClientConnected(ClientConnectedEventArgs e)
|
||||
{
|
||||
EventHandler<ClientConnectedEventArgs> handler = ClientConnected;
|
||||
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user