diff --git a/EasyTcp3/EasyTcp3.Actions/ActionUtils/EasyTcpActionFilter.cs b/EasyTcp3/EasyTcp3.Actions/ActionUtils/EasyTcpActionFilter.cs
index 9cab856..e68fbc9 100644
--- a/EasyTcp3/EasyTcp3.Actions/ActionUtils/EasyTcpActionFilter.cs
+++ b/EasyTcp3/EasyTcp3.Actions/ActionUtils/EasyTcpActionFilter.cs
@@ -1,9 +1,11 @@
+using System;
+
namespace EasyTcp3.Actions.ActionUtils
{
///
/// Filter attribute for EasyTcpActions
///
- public interface IEasyTcpActionFilter
+ public abstract class EasyTcpActionFilter : Attribute
{
///
/// Determines whether client has access to an action
@@ -12,6 +14,6 @@ public interface IEasyTcpActionFilter
/// EasyTcpActionServer/EasyTcpActionClient as sender
///
///
- public bool HasAccess(object sender, ActionMessage message);
+ public abstract bool HasAccess(object sender, ActionMessage message);
}
}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Actions/ActionsCore/Action.cs b/EasyTcp3/EasyTcp3.Actions/ActionsCore/Action.cs
index 001dab0..9033eac 100644
--- a/EasyTcp3/EasyTcp3.Actions/ActionsCore/Action.cs
+++ b/EasyTcp3/EasyTcp3.Actions/ActionsCore/Action.cs
@@ -30,7 +30,7 @@ public class Action
///
/// List with EasyTcpAction filters
///
- public List Filters;
+ public List Filters;
///
/// Instance of EasyTcpActionDelegate*
@@ -50,7 +50,7 @@ public Action(MethodInfo method, Dictionary classInstances)
if (classInstance == null) EasyTcpAction = Delegate.CreateDelegate(methodType, method);
EasyTcpAction = Delegate.CreateDelegate(methodType, classInstance, method);
- var filters = method.GetCustomAttributes().OfType().ToList();
+ var filters = method.GetCustomAttributes().OfType().ToList();
if (filters.Any()) Filters = filters;
}
diff --git a/EasyTcp3/EasyTcp3.Actions/EasyTcp3.Actions.csproj b/EasyTcp3/EasyTcp3.Actions/EasyTcp3.Actions.csproj
index c1fd956..82ccdba 100644
--- a/EasyTcp3/EasyTcp3.Actions/EasyTcp3.Actions.csproj
+++ b/EasyTcp3/EasyTcp3.Actions/EasyTcp3.Actions.csproj
@@ -1,7 +1,7 @@
- netstandard2.1
+ netstandard2.0
true
2.4.0
EasyTcp.Actions
diff --git a/EasyTcp3/EasyTcp3.Actions/EasyTcpActionClient.cs b/EasyTcp3/EasyTcp3.Actions/EasyTcpActionClient.cs
index 8327a1c..ad48966 100644
--- a/EasyTcp3/EasyTcp3.Actions/EasyTcpActionClient.cs
+++ b/EasyTcp3/EasyTcp3.Actions/EasyTcpActionClient.cs
@@ -58,7 +58,7 @@ public EasyTcpActionClient(IEasyTcpProtocol protocol = null, Assembly assembly =
string nameSpace = null) : base(protocol)
{
AddActions(assembly ?? Assembly.GetCallingAssembly(), nameSpace);
- OnDataReceive += async (sender, message) =>
+ OnDataReceiveAsync += async (sender, message) =>
{
try { await Actions.ExecuteAction(Interceptor, FireOnUnknownAction, sender, message); }
catch (Exception ex) { FireOnError(ex); }
diff --git a/EasyTcp3/EasyTcp3.Actions/EasyTcpActionServer.cs b/EasyTcp3/EasyTcp3.Actions/EasyTcpActionServer.cs
index b7c01a7..d1a2c97 100644
--- a/EasyTcp3/EasyTcp3.Actions/EasyTcpActionServer.cs
+++ b/EasyTcp3/EasyTcp3.Actions/EasyTcpActionServer.cs
@@ -59,7 +59,7 @@ public EasyTcpActionServer(IEasyTcpProtocol protocol = null, Assembly assembly =
: base(protocol)
{
AddActions(assembly ?? Assembly.GetCallingAssembly(), nameSpace);
- OnDataReceive += async (sender, message) =>
+ OnDataReceiveAsync += async (sender, message) =>
{
try { await Actions.ExecuteAction(Interceptor, FireOnUnknownAction, sender, message); }
catch (Exception ex) { FireOnError(ex); }
diff --git a/EasyTcp3/EasyTcp3.Encryption/EasyTcp3.Encryption.csproj b/EasyTcp3/EasyTcp3.Encryption/EasyTcp3.Encryption.csproj
index fbacb41..f61efd0 100644
--- a/EasyTcp3/EasyTcp3.Encryption/EasyTcp3.Encryption.csproj
+++ b/EasyTcp3/EasyTcp3.Encryption/EasyTcp3.Encryption.csproj
@@ -1,7 +1,7 @@
- netstandard2.1
+ netstandard2.0
true
2.2.1
EasyTcp.Encryption
@@ -17,7 +17,7 @@
-
+
diff --git a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/EncryptedPrefixLengthProtocol.cs b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/EncryptedPrefixLengthProtocol.cs
index f2d4f07..554af90 100644
--- a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/EncryptedPrefixLengthProtocol.cs
+++ b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/EncryptedPrefixLengthProtocol.cs
@@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Net.Sockets;
+using System.Threading.Tasks;
using EasyEncrypt2;
using EasyTcp3.Protocols;
using EasyTcp3.Protocols.Tcp;
@@ -84,11 +85,11 @@ public override byte[] CreateMessage(params byte[][] data)
///
/// ignored
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
if (!(ReceivingLength = !ReceivingLength))
{
- BufferSize = BitConverter.ToUInt16(client.Buffer, 0);
+ BufferSize = BitConverter.ToUInt16(data, 0);
if (BufferSize == 0) client.Dispose();
}
else
@@ -96,7 +97,7 @@ public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient c
BufferSize = 2;
try
{
- client.DataReceiveHandler(new Message(client.Buffer, client).Decrypt(Encrypter));
+ await client.DataReceiveHandler(new Message(data, client).Decrypt(Encrypter));
}
catch { OnDecryptionError(client); }
}
diff --git a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DefaultSslProtocol.cs b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DefaultSslProtocol.cs
index d229a1d..d1be203 100644
--- a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DefaultSslProtocol.cs
+++ b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DefaultSslProtocol.cs
@@ -3,6 +3,7 @@
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
using EasyTcp3.Protocols;
using EasyTcp3.Server;
@@ -13,6 +14,8 @@ namespace EasyTcp3.Encryption.Protocols.Tcp.Ssl
///
public abstract class DefaultSslProtocol : IEasyTcpProtocol
{
+ public byte[] ReceiveBuffer;
+
///
/// Instance of SslStream,
/// null for base protocol of server
@@ -80,8 +83,15 @@ public virtual Socket GetSocket(AddressFamily addressFamily) =>
///
public virtual void StartAcceptingClients(EasyTcpServer server)
{
- server.BaseSocket.Listen(5000);
- server.BaseSocket.BeginAccept(OnConnectCallback, server);
+ if (server.AcceptArgs == null)
+ {
+ server.BaseSocket.Listen(50000);
+ server.AcceptArgs = new SocketAsyncEventArgs {UserToken = server};
+ server.AcceptArgs.Completed += (_, ar) => OnConnectCallback(ar);
+ }
+
+ server.AcceptArgs.AcceptSocket = null;
+ if (!server.BaseSocket.AcceptAsync(server.AcceptArgs)) OnConnectCallback(server.AcceptArgs);
}
///
@@ -92,8 +102,10 @@ public virtual void EnsureDataReceiverIsRunning(EasyTcpClient client)
{
if (IsListening) return;
IsListening = true;
- ((DefaultSslProtocol) client.Protocol).SslStream.BeginRead(client.Buffer = new byte[BufferSize], 0,
- client.Buffer.Length, OnReceiveCallback, client);
+
+ var protocol = (DefaultSslProtocol)client.Protocol;
+ ((DefaultSslProtocol) client.Protocol).SslStream.BeginRead(protocol.ReceiveBuffer = new byte[BufferSize], 0,
+ protocol.ReceiveBuffer.Length, OnReceiveCallback, client);
}
///
@@ -114,7 +126,7 @@ public virtual void SendMessage(EasyTcpClient client, byte[] message)
if (client?.BaseSocket == null || !client.BaseSocket.Connected)
throw new Exception("Could not send data: Client not connected or null");
- client.FireOnDataSend(new Message(message, client));
+ client.FireOnDataSend(message, client);
SslStream.BeginWrite(message, 0, message.Length, ar =>
{
var stream = ar.AsyncState as SslStream;
@@ -192,7 +204,7 @@ public virtual bool OnConnectServer(EasyTcpClient client)
/// received data, has size of clients buffer
/// amount of received bytes
///
- public abstract void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client);
+ public abstract Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client);
/*
* Internal methods
@@ -231,29 +243,30 @@ protected virtual void HandleDisconnect(EasyTcpClient client)
/// Fired when new client connects
///
///
- protected virtual void OnConnectCallback(IAsyncResult ar)
+ protected virtual void OnConnectCallback(SocketAsyncEventArgs ar)
{
- var server = ar.AsyncState as EasyTcpServer;
+ var server = ar.UserToken as EasyTcpServer;
if (server?.BaseSocket == null || !server.IsRunning) return;
try
{
- var client = new EasyTcpClient(server.BaseSocket.EndAccept(ar),
+ var client = new EasyTcpClient(ar.AcceptSocket,
(IEasyTcpProtocol) server.Protocol.Clone())
{
Serialize = server.Serialize,
Deserialize = server.Deserialize
};
- client.OnDataReceive += (_, message) => server.FireOnDataReceive(message);
+ client.OnDataReceiveAsync += async (_, message) => await server.FireOnDataReceive(message);
client.OnDataSend += (_, message) => server.FireOnDataSend(message);
client.OnDisconnect += (_, c) => server.FireOnDisconnect(c);
client.OnError += (_, exception) => server.FireOnError(exception);
- server.BaseSocket.BeginAccept(OnConnectCallback, server);
+
+ StartAcceptingClients(server);
if (!client.Protocol.OnConnectServer(client)) return;
server.FireOnConnect(client);
- if (client.BaseSocket != null) //Check if user aborted OnConnect with Client.Dispose()
- lock (server.UnsafeConnectedClients)
+ if (client.BaseSocket != null) // Check if user aborted OnConnect with Client.Dispose()
+ lock (server.UnsafeConnectedClients)
server.UnsafeConnectedClients.Add(client);
}
catch (Exception ex)
@@ -267,7 +280,7 @@ protected virtual void OnConnectCallback(IAsyncResult ar)
/// Fired when new data is received
///
///
- protected virtual void OnReceiveCallback(IAsyncResult ar)
+ protected virtual async void OnReceiveCallback(IAsyncResult ar)
{
var client = ar.AsyncState as EasyTcpClient;
if (client == null) return;
@@ -278,7 +291,9 @@ protected virtual void OnReceiveCallback(IAsyncResult ar)
int receivedBytes = SslStream.EndRead(ar);
if (receivedBytes != 0)
{
- DataReceive(client.Buffer, receivedBytes, client);
+ var protocol = (DefaultSslProtocol)client.Protocol;
+ await DataReceive(protocol.ReceiveBuffer, receivedBytes, client);
+
if (client.BaseSocket == null)
HandleDisconnect(client); // Check if client is disposed by DataReceive
else EnsureDataReceiverIsRunning(client);
diff --git a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DelimiterSslProtocol.cs b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DelimiterSslProtocol.cs
index 154424e..f99ba98 100644
--- a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DelimiterSslProtocol.cs
+++ b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/DelimiterSslProtocol.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
+using System.Threading.Tasks;
namespace EasyTcp3.Encryption.Protocols.Tcp.Ssl
{
@@ -157,7 +158,7 @@ public override object Clone()
/// received data, has size of clients buffer
/// amount of received bytes
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
byte receivedByte = data[0]; // Size of buffer is always 1
ReceivedBytes.Add(receivedByte);
@@ -173,7 +174,7 @@ public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient c
byte[] receivedData = AutoRemoveDelimiter
? ReceivedBytes.Take(receivedBytesLength).ToArray() // Remove delimiter from message
: ReceivedBytes.ToArray();
- client.DataReceiveHandler(new Message(receivedData, client));
+ await client.DataReceiveHandler(new Message(receivedData, client));
ReceivedBytes.Clear();
}
}
diff --git a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/NoneSslProtocol.cs b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/NoneSslProtocol.cs
index 1ceebbd..234ccb2 100644
--- a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/NoneSslProtocol.cs
+++ b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/NoneSslProtocol.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
namespace EasyTcp3.Encryption.Protocols.Tcp.Ssl
{
@@ -82,11 +83,11 @@ public override object Clone()
/// received data, has size of clients buffer
/// amount of received bytes
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
byte[] receivedData = new byte[receivedBytes];
Buffer.BlockCopy(data,0,receivedData,0,receivedBytes);
- client.DataReceiveHandler(new Message(receivedData, client));
+ await client.DataReceiveHandler(new Message(receivedData, client));
}
}
}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/PrefixLengthSslProtocol.cs b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/PrefixLengthSslProtocol.cs
index 428696e..583cdd6 100644
--- a/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/PrefixLengthSslProtocol.cs
+++ b/EasyTcp3/EasyTcp3.Encryption/Protocols/Tcp/Ssl/PrefixLengthSslProtocol.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
namespace EasyTcp3.Encryption.Protocols.Tcp.Ssl
{
@@ -83,17 +84,17 @@ public override object Clone()
///
/// ignored
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
if (!(ReceivingLength = !ReceivingLength))
{
- BufferSize = BitConverter.ToUInt16(client.Buffer, 0);
+ BufferSize = BitConverter.ToUInt16(data, 0);
if (BufferSize == 0) client.Dispose();
}
else
{
BufferSize = 2;
- client.DataReceiveHandler(new Message(client.Buffer, client));
+ await client.DataReceiveHandler(new Message(data, client));
}
}
}
diff --git a/EasyTcp3/EasyTcp3.Examples/Actions/AuthorizationExample.cs b/EasyTcp3/EasyTcp3.Examples/Actions/AuthorizationExample.cs
index cfa7911..f746ea2 100644
--- a/EasyTcp3/EasyTcp3.Examples/Actions/AuthorizationExample.cs
+++ b/EasyTcp3/EasyTcp3.Examples/Actions/AuthorizationExample.cs
@@ -62,7 +62,7 @@ public static void Connect()
* example filter attribute for authorization
*/
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
- public class EasyTcpAuthorization : Attribute, IEasyTcpActionFilter
+ public class EasyTcpAuthorization : EasyTcpActionFilter
{
private readonly UserRole[] _allowedRoles;
@@ -83,7 +83,7 @@ public class EasyTcpAuthorization : Attribute, IEasyTcpActionFilter
///
///
///
- public bool HasAccess(object sender, ActionMessage message)
+ public override bool HasAccess(object sender, ActionMessage message)
{
var hasRole = message.Client.Session.TryGetValue("UserRole", out object userRole);
if (!hasRole) return false;
diff --git a/EasyTcp3/EasyTcp3.Examples/LargeArray/LargeArrayExample.cs b/EasyTcp3/EasyTcp3.Examples/LargeArray/LargeArrayExample.cs
index ad62041..8e09cdf 100644
--- a/EasyTcp3/EasyTcp3.Examples/LargeArray/LargeArrayExample.cs
+++ b/EasyTcp3/EasyTcp3.Examples/LargeArray/LargeArrayExample.cs
@@ -34,7 +34,7 @@ public static void Connect()
client.SendLargeArray(new byte[1000000]);
// Send large array without length prefix
- client.SendLargeArray(new byte[10000], false);
+ client.SendLargeArray(new byte[10000], sendLengthPrefix: false);
Console.ReadLine();
}
@@ -50,7 +50,7 @@ public async Task LargeArrayReceive(Message message)
Console.WriteLine($"Received {largeArray.Length} bytes");
// Receive array with known length
- var largeArray2 = await message.ReceiveLargeArrayAsync(10000);
+ var largeArray2 = await message.ReceiveLargeArrayAsync(count: 10000);
Console.WriteLine($"Received {largeArray2.Length} bytes");
}
}
diff --git a/EasyTcp3/EasyTcp3.Examples/Program.cs b/EasyTcp3/EasyTcp3.Examples/Program.cs
index 3f986c5..702ff0c 100644
--- a/EasyTcp3/EasyTcp3.Examples/Program.cs
+++ b/EasyTcp3/EasyTcp3.Examples/Program.cs
@@ -8,7 +8,7 @@ class Program
static void Main()
{
// Run test methods here
- MultiThreadedActionSpeedTest.Run();
+ ThroughputTest.Run();
}
}
}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Examples/SpeedTest/ActionSpeedTestClient.cs b/EasyTcp3/EasyTcp3.Examples/SpeedTest/ActionSpeedTestClient.cs
deleted file mode 100644
index 25e0fb6..0000000
--- a/EasyTcp3/EasyTcp3.Examples/SpeedTest/ActionSpeedTestClient.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Net;
-using System.Text;
-using System.Threading;
-using EasyTcp3.Actions;
-using EasyTcp3.Actions.ActionUtils;
-using EasyTcp3.ClientUtils;
-using EasyTcp3.Server;
-using EasyTcp3.Server.ServerUtils;
-
-namespace EasyTcp3.Examples.SpeedTest
-{
- ///
- /// This class contains a basic speedtest of the SendActionAndGetReply method,
- /// this includes the Send and Receive functions + the actions performance
- ///
- /// It uses the action echo server as test server
- ///
- public static class ActionSpeedTestClient
- {
- const int Port = 5_001;
- const int MessageCount = 1000_000;
- const string Message = "Message";
-
- public static void RunSpeedTest()
- {
- using var server = new EasyTcpActionServer().Start(Port);
-
- var client = new EasyTcpClient();
- if (!client.Connect(IPAddress.Loopback, Port)) return;
-
- byte[] message = Encoding.UTF8.GetBytes(Message);
- using var resetEvent = new ManualResetEventSlim();
- Stopwatch sw = new Stopwatch();
- sw.Start();
-
- int counter = 0;
- client.OnDataReceive += (o, message) =>
- {
- if(Interlocked.Increment(ref counter) == MessageCount) resetEvent.Set();
- };
-
- for (int x = 0; x < MessageCount; x++) client.SendAction("ECHO", message);
-
- resetEvent.Wait();
- Console.WriteLine($"Send {counter} action messages");
- Console.WriteLine($"ElapsedMilliseconds SpeedTest: {sw.ElapsedMilliseconds}");
- Console.WriteLine($"Average SpeedTest: {sw.ElapsedMilliseconds / (double) MessageCount}");
- Console.WriteLine($"Messages/Second: {MessageCount / sw.Elapsed.TotalSeconds}");
- }
- }
-}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Examples/SpeedTest/MultiThreadedActionSpeedTest.cs b/EasyTcp3/EasyTcp3.Examples/SpeedTest/MultiThreadedActionSpeedTest.cs
deleted file mode 100644
index 84c0b31..0000000
--- a/EasyTcp3/EasyTcp3.Examples/SpeedTest/MultiThreadedActionSpeedTest.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.Net;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using EasyTcp3.Actions;
-using EasyTcp3.Actions.ActionUtils;
-using EasyTcp3.ClientUtils;
-using EasyTcp3.Protocols;
-using EasyTcp3.Protocols.Tcp;
-using EasyTcp3.Server.ServerUtils;
-
-namespace EasyTcp3.Examples.SpeedTest
-{
- public class MultiThreadedActionSpeedTest
- {
- const int ClientsCount = 20_000; // Max: ushort / 2 because of ip restrictions
- const int MessageCount = 1_000_000;
- private static readonly string MessageDataString = new string('H', 100);
- const int Port = 50013;
- private const int ThreadAmount = 8;
- private static readonly IEasyTcpProtocol ServerProtocol = new PrefixLengthProtocol();
- private static readonly IEasyTcpProtocol ClientProtocol = new PrefixLengthProtocol();
-
- public static void Run()
- {
- using var server = new EasyTcpActionServer(ServerProtocol).Start(Port);
-
- byte[] messageData = Encoding.UTF8.GetBytes(MessageDataString);
- var clientList = new ConcurrentQueue();
- int counter = 0;
- using var resetEvent = new ManualResetEventSlim();
- Stopwatch st = Stopwatch.StartNew();
-
- Parallel.For(0, ClientsCount, new ParallelOptions {MaxDegreeOfParallelism = ThreadAmount}, i =>
- {
- var client = new EasyTcpClient((IEasyTcpProtocol) ClientProtocol.Clone());
- client.OnDataReceive += (o, message) =>
- {
- if(Interlocked.Increment(ref counter) == MessageCount) resetEvent.Set();
- };
- if (client.Connect(IPAddress.Any, Port)) clientList.Enqueue(client);
- });
- Console.WriteLine($"Connected with {clientList.Count} clients");
- Console.WriteLine($"Total: {st.ElapsedMilliseconds}ms");
- Console.WriteLine($"Average milliseconds per client: {st.ElapsedMilliseconds / (double) clientList.Count}");
- Console.WriteLine($"Connections/Second: {clientList.Count / st.Elapsed.TotalSeconds}");
-
- Console.WriteLine($"\n\nSending {MessageCount} messages");
- st.Restart();
- Parallel.For(0, MessageCount, new ParallelOptions {MaxDegreeOfParallelism = ThreadAmount}, i =>
- {
- clientList.TryDequeue(out EasyTcpClient client);
- client.SendAction("ECHO", messageData);
- clientList.Enqueue(client);
- });
-
- resetEvent.Wait();
- Console.WriteLine($"Total: {st.ElapsedMilliseconds}ms");
- Console.WriteLine($"Average milliseconds per message: {st.ElapsedMilliseconds / (double) MessageCount}");
- Console.WriteLine($"Messages/Second: {MessageCount / st.Elapsed.TotalSeconds}");
-
- foreach (var client in clientList) client.Dispose();
- Console.ReadLine();
- }
- }
-}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Examples/SpeedTest/MultiThreadedSpeedTest.cs b/EasyTcp3/EasyTcp3.Examples/SpeedTest/MultiThreadedSpeedTest.cs
deleted file mode 100644
index 533bd39..0000000
--- a/EasyTcp3/EasyTcp3.Examples/SpeedTest/MultiThreadedSpeedTest.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.Net;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using EasyTcp3.ClientUtils;
-using EasyTcp3.Protocols;
-using EasyTcp3.Protocols.Tcp;
-using EasyTcp3.Server;
-using EasyTcp3.Server.ServerUtils;
-
-namespace EasyTcp3.Examples.SpeedTest
-{
- public static class MultiThreadedSpeedTest
- {
- const int ClientsCount = 20_000; // Max: ushort / 2 because of ip restrictions
- const int MessageCount = 1_000_000;
- private static readonly string MessageDataString = new string('H', 100);
- const int Port = 50013;
- private const int ThreadAmount = 8;
- private static readonly IEasyTcpProtocol ServerProtocol = new PrefixLengthProtocol();
- private static readonly IEasyTcpProtocol ClientProtocol = new PrefixLengthProtocol();
-
- public static void Run()
- {
- using var server = new EasyTcpServer(ServerProtocol).Start(Port);
- server.OnDataReceive += (o, message) => message.Client.Send(message);
-
- byte[] messageData = Encoding.UTF8.GetBytes(MessageDataString);
- var clientList = new ConcurrentQueue();
- int counter = 0;
- using var resetEvent = new ManualResetEventSlim();
- Stopwatch st = Stopwatch.StartNew();
-
- Parallel.For(0, ClientsCount, new ParallelOptions {MaxDegreeOfParallelism = ThreadAmount}, i =>
- {
- var client = new EasyTcpClient((IEasyTcpProtocol) ClientProtocol.Clone());
- client.OnDataReceive += (o, message) =>
- {
- if(Interlocked.Increment(ref counter) == MessageCount) resetEvent.Set();
- };
- if (client.Connect(IPAddress.Any, Port)) clientList.Enqueue(client);
- });
- Console.WriteLine($"Connected with {clientList.Count} clients");
- Console.WriteLine($"Total: {st.ElapsedMilliseconds}ms");
- Console.WriteLine($"Average milliseconds per client: {st.ElapsedMilliseconds / (double) clientList.Count}");
- Console.WriteLine($"Connections/Second: {clientList.Count / st.Elapsed.TotalSeconds}");
-
- Console.WriteLine($"\n\nSending {MessageCount} messages");
- st.Restart();
- Parallel.For(0, MessageCount, new ParallelOptions {MaxDegreeOfParallelism = ThreadAmount}, i =>
- {
- clientList.TryDequeue(out EasyTcpClient client);
- client.Send(messageData);
- clientList.Enqueue(client);
- });
-
- resetEvent.Wait();
- Console.WriteLine($"Total: {st.ElapsedMilliseconds}ms");
- Console.WriteLine($"Average milliseconds per message: {st.ElapsedMilliseconds / (double) MessageCount}");
- Console.WriteLine($"Messages/Second: {MessageCount / st.Elapsed.TotalSeconds}");
-
- foreach (var client in clientList) client.Dispose();
- Console.ReadLine();
- }
- }
-}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Examples/SpeedTest/SpeedTestClient.cs b/EasyTcp3/EasyTcp3.Examples/SpeedTest/SpeedTestClient.cs
deleted file mode 100644
index 52d1a01..0000000
--- a/EasyTcp3/EasyTcp3.Examples/SpeedTest/SpeedTestClient.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Net;
-using System.Text;
-using System.Threading;
-using EasyTcp3.ClientUtils;
-using EasyTcp3.Server;
-using EasyTcp3.Server.ServerUtils;
-
-namespace EasyTcp3.Examples.SpeedTest
-{
- ///
- /// This class contains a basic speedtest of the SendAndGetReply method,
- /// this includes the Send and Receive functions
- ///
- /// It uses the echo server as test server
- ///
- public static class SpeedTestClient
- {
- const int Port = 5_001;
- const int MessageCount = 100_000;
- const string Message = "Message";
-
- public static void RunSpeedTest()
- {
- using var server = new EasyTcpServer().Start(Port);
- server.OnDataReceive += (o, message) => message.Client.Send(message);
-
- var client = new EasyTcpClient();
- if (!client.Connect(IPAddress.Loopback, Port)) return;
-
- byte[] message = Encoding.UTF8.GetBytes(Message);
- using var resetEvent = new ManualResetEventSlim();
- Stopwatch sw = new Stopwatch();
- sw.Start();
-
- int counter = 0;
- client.OnDataReceive += (o, message) =>
- {
- if(Interlocked.Increment(ref counter) == MessageCount) resetEvent.Set();
- };
-
- for (int x = 0; x < MessageCount; x++) client.Send(message);
-
- resetEvent.Wait();
- Console.WriteLine($"Send {counter} messages");
- Console.WriteLine($"ElapsedMilliseconds SpeedTest: {sw.ElapsedMilliseconds}");
- Console.WriteLine($"Average SpeedTest: {sw.ElapsedMilliseconds / (double) MessageCount}");
- Console.WriteLine($"Messages/Second: {MessageCount / sw.Elapsed.TotalSeconds}");
- }
- }
-}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Examples/SpeedTest/ThroughputTest.cs b/EasyTcp3/EasyTcp3.Examples/SpeedTest/ThroughputTest.cs
new file mode 100644
index 0000000..0c47ede
--- /dev/null
+++ b/EasyTcp3/EasyTcp3.Examples/SpeedTest/ThroughputTest.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using EasyTcp3.ClientUtils;
+using EasyTcp3.Server;
+using EasyTcp3.Server.ServerUtils;
+
+namespace EasyTcp3.Examples.SpeedTest
+{
+ public class ThroughputTest
+ {
+ const int ClientsCount = 100; // Max: ushort / 2 because of ip restrictions
+ private static readonly string MessageDataString = new string('H', 100);
+ const int Port = 1111;
+ private const int ThreadAmount = 16;
+
+ public static void Run()
+ {
+
+
+ byte[] messageData = Encoding.UTF8.GetBytes(MessageDataString);
+ var clientList = new ConcurrentQueue();
+ int counter = 0;
+ Stopwatch st = Stopwatch.StartNew();
+
+ Parallel.For(0, ClientsCount, new ParallelOptions {MaxDegreeOfParallelism = ThreadAmount}, i =>
+ {
+ var client = new EasyTcpClient();
+ client.OnConnect += (o, client) => client.Send(messageData);
+ client.OnDataReceive += (o,message) =>
+ {
+ Interlocked.Increment(ref counter);
+ message.Client.Send(message);
+ };
+ var socket = client.Protocol.GetSocket(AddressFamily.InterNetwork);
+ socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
+ socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
+ if (client.Connect(IPAddress.Any, Port, socket: socket)) clientList.Enqueue(client);
+ });
+
+ while (true)
+ {
+ Console.Clear();
+ Console.WriteLine($"Total: {st.ElapsedMilliseconds}ms, {counter} messages");
+ Console.WriteLine($"Average response time server in milliseconds: {st.ElapsedMilliseconds / (double) counter * ClientsCount}");
+ Console.WriteLine($"Average milliseconds spend per message: {st.ElapsedMilliseconds / (double) counter}");
+ Console.WriteLine($"Messages/Second: {counter / st.Elapsed.TotalSeconds}");
+ Task.Delay(50).Wait();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Examples/Streams/StreamExample.cs b/EasyTcp3/EasyTcp3.Examples/Streams/StreamExample.cs
index e9bba8e..9c01c2a 100644
--- a/EasyTcp3/EasyTcp3.Examples/Streams/StreamExample.cs
+++ b/EasyTcp3/EasyTcp3.Examples/Streams/StreamExample.cs
@@ -35,7 +35,7 @@ public static void Connect()
// Send stream without length prefix
var stream2 = new MemoryStream(new byte[10000]);
- client.SendStream(stream2, false);
+ client.SendStream(stream2, sendLengthPrefix: false);
Console.ReadLine();
// Writing / reading the base stream is also possible
@@ -56,7 +56,7 @@ public async Task ReceiveStream(Message message)
// Receive stream with known length
await using var stream2 = new MemoryStream();
- await message.ReceiveStreamAsync(stream2, 10000);
+ await message.ReceiveStreamAsync(stream2, count: 10000);
Console.WriteLine($"Received {stream2.Length} bytes");
}
}
diff --git a/EasyTcp3/EasyTcp3.Logging/EasyTcp3.Logging.csproj b/EasyTcp3/EasyTcp3.Logging/EasyTcp3.Logging.csproj
index 7bae677..e21fdae 100644
--- a/EasyTcp3/EasyTcp3.Logging/EasyTcp3.Logging.csproj
+++ b/EasyTcp3/EasyTcp3.Logging/EasyTcp3.Logging.csproj
@@ -1,7 +1,7 @@
- netstandard2.1
+ netstandard2.0
true
1.1.0
EasyTcp.Logging
@@ -14,6 +14,7 @@
EasyTcp.Logging
true
Socket Networking Tcp TcpClient TcpServer Server SimpleTcp EasyTcp AsyncTcp Logging
+ 8
diff --git a/EasyTcp3/EasyTcp3.Test/Actions/Filter/FilterTest.cs b/EasyTcp3/EasyTcp3.Test/Actions/Filter/FilterTest.cs
index c279bdc..48c6a8f 100644
--- a/EasyTcp3/EasyTcp3.Test/Actions/Filter/FilterTest.cs
+++ b/EasyTcp3/EasyTcp3.Test/Actions/Filter/FilterTest.cs
@@ -1,4 +1,3 @@
-using System;
using System.Threading;
using EasyTcp3.Actions;
using EasyTcp3.Actions.ActionUtils;
@@ -39,9 +38,9 @@ public void TestFilters()
public void Auth() => Interlocked.Increment(ref _counter);
}
- public class EasyTcpTestAuthorization : Attribute, IEasyTcpActionFilter
+ public class EasyTcpTestAuthorization : EasyTcpActionFilter
{
- public bool HasAccess(object sender, ActionMessage message)
+ public override bool HasAccess(object sender, ActionMessage message)
{
if (message.Client.Session.TryGetValue("role", out object role) && role as string == "user") return true;
else return false;
diff --git a/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamAsync.cs b/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamAsync.cs
index 9158f2d..9ea487e 100644
--- a/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamAsync.cs
+++ b/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamAsync.cs
@@ -27,10 +27,10 @@ public async Task Stream1() //Client -> -(Stream)> Server (Client sends mess
string testData = "123", data = "";
- server.OnDataReceive += (sender, message) => //Receive stream from client
+ server.OnDataReceiveAsync += async (sender, message) => //Receive stream from client
{
- using var stream = new MemoryStream();
- message.ReceiveStreamAsync(stream).Wait();
+ await using var stream = new MemoryStream();
+ await message.ReceiveStreamAsync(stream);
data = Encoding.UTF8.GetString(stream.ToArray());
};
@@ -55,14 +55,14 @@ public void Stream2()//Client -> Server -(Stream)> Client (Client requests s
using var client = new EasyTcpClient();
Assert.IsTrue(client.Connect(IPAddress.Any, port));
- server.OnDataReceive += (sender, message) => //Send stream if client requests
+ server.OnDataReceiveAsync += async (sender, message) => //Send stream if client requests
{
- using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
+ await using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
message.Client.Send("Stream");
- message.Client.SendStreamAsync(dataStream).Wait();
+ await message.Client.SendStreamAsync(dataStream);
};
- client.OnDataReceive += async (sender, message) => //Receive stream from server
+ client.OnDataReceiveAsync += async (sender, message) => //Receive stream from server
{
await using var stream = new MemoryStream();
await message.ReceiveStreamAsync(stream);
diff --git a/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamCompression.cs b/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamCompression.cs
new file mode 100644
index 0000000..ff2b386
--- /dev/null
+++ b/EasyTcp3/EasyTcp3.Test/EasyTcp/Client/Stream/StreamCompression.cs
@@ -0,0 +1,40 @@
+using System.IO;
+using System.Net;
+using System.Text;
+using EasyTcp3.ClientUtils;
+using EasyTcp3.Server;
+using EasyTcp3.Server.ServerUtils;
+using NUnit.Framework;
+
+namespace EasyTcp3.Test.EasyTcp.Client.Stream
+{
+ public class StreamCompression
+ {
+ [Test]
+ public void Stream1() //Client -> -(Stream)> Server (Client sends message to server)
+ {
+ ushort port = TestHelper.GetPort();
+ using var server = new EasyTcpServer().Start(port);
+
+ using var client = new EasyTcpClient();
+ Assert.IsTrue(client.Connect(IPAddress.Any, port));
+
+ string testData = "123", data = null;
+
+ server.OnDataReceive += (sender, message) => //Receive stream from client
+ {
+ using var stream = new MemoryStream();
+ message.ReceiveStream(stream, compression: true);
+ data = Encoding.UTF8.GetString(stream.ToArray());
+ };
+
+ //Send stream to server
+ using var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(testData));
+ client.Send("Stream");
+ client.SendStream(dataStream, compression: true);
+
+ TestHelper.WaitWhileTrue(() => data == null);
+ Assert.AreEqual(testData, data);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3.Test/Encryption/Ssl/StreamSsl.cs b/EasyTcp3/EasyTcp3.Test/Encryption/Ssl/StreamSsl.cs
index 89daaa4..247976c 100644
--- a/EasyTcp3/EasyTcp3.Test/Encryption/Ssl/StreamSsl.cs
+++ b/EasyTcp3/EasyTcp3.Test/Encryption/Ssl/StreamSsl.cs
@@ -24,9 +24,9 @@ public void Stream()
string testData = "123", data = null;
- server.OnDataReceive += (sender, message) => //Receive stream from client
+ server.OnDataReceiveAsync += async (sender, message) => //Receive stream from client
{
- using var stream = new MemoryStream();
+ await using var stream = new MemoryStream();
message.ReceiveStream(stream);
data = Encoding.UTF8.GetString(stream.ToArray());
};
diff --git a/EasyTcp3/EasyTcp3/ClientUtils/Async/LargeArrayAsyncUtil.cs b/EasyTcp3/EasyTcp3/ClientUtils/Async/LargeArrayAsyncUtil.cs
index 655d57e..283253b 100644
--- a/EasyTcp3/EasyTcp3/ClientUtils/Async/LargeArrayAsyncUtil.cs
+++ b/EasyTcp3/EasyTcp3/ClientUtils/Async/LargeArrayAsyncUtil.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.IO.Compression;
using System.Threading.Tasks;
namespace EasyTcp3.ClientUtils.Async
@@ -15,14 +16,17 @@ public static class ArrayAsyncUtil
///
///
///
+ ///
/// determines whether prefix with length of the data is send
- public static async Task SendLargeArrayAsync(this EasyTcpClient client, byte[] array, bool sendLengthPrefix = true)
+ public static async Task SendLargeArrayAsync(this EasyTcpClient client, byte[] array,bool compression = false, bool sendLengthPrefix = true)
{
if(client?.BaseSocket == null) throw new Exception("Client is not connected");
- await using var networkStream = client.Protocol.GetStream(client);
- if(sendLengthPrefix) await networkStream.WriteAsync(BitConverter.GetBytes(array.Length));
- await networkStream.WriteAsync(array);
+ using var networkStream = client.Protocol.GetStream(client);
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Compress) : networkStream;
+
+ if(sendLengthPrefix) await dataStream.WriteAsync(BitConverter.GetBytes(array.Length),0, 4);
+ await dataStream.WriteAsync(array,0,array.Length);
}
///
@@ -30,28 +34,30 @@ public static async Task SendLargeArrayAsync(this EasyTcpClient client, byte[] a
/// Use this method only when not listening for incoming messages (In the OnReceive event)
///
///
+ ///
/// length of data, use prefix when 0
///
/// stream is not writable
- public static async Task ReceiveLargeArrayAsync(this Message message, int count = 0, int bufferSize = 1024)
+ public static async Task ReceiveLargeArrayAsync(this Message message, bool compression = false, int count = 0, int bufferSize = 1024)
{
if(message?.Client?.BaseSocket == null) throw new Exception("Client is not connected");
- await using var networkStream = message.Client.Protocol.GetStream(message.Client);
+ using var networkStream = message.Client.Protocol.GetStream(message.Client);
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Decompress) : networkStream;
// Get length from stream
if (count == 0)
{
var length = new byte[4];
- await networkStream.ReadAsync(length, 0, length.Length);
- count = BitConverter.ToInt32(length);
+ await dataStream.ReadAsync(length, 0, length.Length);
+ count = BitConverter.ToInt32(length, 0);
}
var receivedArray = new byte[count];
int read, totalReceivedBytes = 0;
while (totalReceivedBytes < count &&
- (read = await networkStream.ReadAsync(receivedArray, totalReceivedBytes, Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
+ (read = await dataStream.ReadAsync(receivedArray, totalReceivedBytes, Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
totalReceivedBytes += read;
return receivedArray;
}
diff --git a/EasyTcp3/EasyTcp3/ClientUtils/Async/ReceiveAsyncUtil.cs b/EasyTcp3/EasyTcp3/ClientUtils/Async/ReceiveAsyncUtil.cs
index 42ee7c6..f42ba95 100644
--- a/EasyTcp3/EasyTcp3/ClientUtils/Async/ReceiveAsyncUtil.cs
+++ b/EasyTcp3/EasyTcp3/ClientUtils/Async/ReceiveAsyncUtil.cs
@@ -32,6 +32,7 @@ public static async Task ReceiveAsync(this EasyTcpClient client, TimeSp
// Function is no longer used when signal is disposed, therefore ignore this warning
// ReSharper disable once AccessToDisposedClosure
signal.Release();
+ return Task.CompletedTask;
};
await signal.WaitAsync(timeout ?? TimeSpan.FromMilliseconds(DefaultTimeout));
diff --git a/EasyTcp3/EasyTcp3/ClientUtils/Async/StreamAsyncUtil.cs b/EasyTcp3/EasyTcp3/ClientUtils/Async/StreamAsyncUtil.cs
index 85bd9e9..7499f7f 100644
--- a/EasyTcp3/EasyTcp3/ClientUtils/Async/StreamAsyncUtil.cs
+++ b/EasyTcp3/EasyTcp3/ClientUtils/Async/StreamAsyncUtil.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.IO.Compression;
using System.Threading.Tasks;
namespace EasyTcp3.ClientUtils.Async
@@ -15,23 +16,27 @@ public static class StreamAsyncUtil
///
///
/// input stream
+ ///
/// determines whether prefix with length of the data is send
///
/// stream is not readable
- public static async Task SendStreamAsync(this EasyTcpClient client, Stream stream, bool sendLengthPrefix = true,
+ public static async Task SendStreamAsync(this EasyTcpClient client, Stream stream, bool compression = false,
+ bool sendLengthPrefix = true,
int bufferSize = 1024)
{
- if(client?.BaseSocket == null) throw new Exception("Client is not connected");
+ if (client?.BaseSocket == null) throw new Exception("Client is not connected");
if (!stream.CanRead) throw new InvalidDataException("Stream is not readable");
- await using var networkStream = client.Protocol.GetStream(client);
- if (sendLengthPrefix) await networkStream.WriteAsync(BitConverter.GetBytes(stream.Length));
+ using var networkStream = client.Protocol.GetStream(client);
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Decompress) : networkStream;
+
+ if (sendLengthPrefix) await dataStream.WriteAsync(BitConverter.GetBytes(stream.Length), 0, 8);
var buffer = new byte[bufferSize];
int read;
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
- await networkStream.WriteAsync(buffer, 0, read);
+ await dataStream.WriteAsync(buffer, 0, read);
}
///
@@ -40,23 +45,26 @@ public static async Task SendStreamAsync(this EasyTcpClient client, Stream strea
///
///
/// output stream for receiving data
+ ///
/// length of data, use prefix when 0
///
/// stream is not writable
- public static async Task ReceiveStreamAsync(this Message message, Stream stream, long count = 0,
+ public static async Task ReceiveStreamAsync(this Message message, Stream stream, bool compression = false,
+ long count = 0,
int bufferSize = 1024)
{
- if(message?.Client?.BaseSocket == null) throw new Exception("Client is not connected");
+ if (message?.Client?.BaseSocket == null) throw new Exception("Client is not connected");
if (!stream.CanWrite) throw new InvalidDataException("Stream is not writable");
- await using var networkStream = message.Client.Protocol.GetStream(message.Client);
+ using var networkStream = message.Client.Protocol.GetStream(message.Client);
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Decompress) : networkStream;
//Get length of stream
if (count == 0)
{
var length = new byte[8];
- await networkStream.ReadAsync(length, 0, length.Length);
- count = BitConverter.ToInt64(length);
+ await dataStream.ReadAsync(length, 0, length.Length);
+ count = BitConverter.ToInt64(length, 0);
}
var buffer = new byte[bufferSize];
@@ -64,7 +72,8 @@ public static async Task ReceiveStreamAsync(this Message message, Stream stream,
int read;
while (totalReceivedBytes < count &&
- (read = await networkStream.ReadAsync(buffer, 0, (int)Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
+ (read = await dataStream.ReadAsync(buffer, 0,
+ (int) Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
{
await stream.WriteAsync(buffer, 0, read);
totalReceivedBytes += read;
diff --git a/EasyTcp3/EasyTcp3/ClientUtils/LargeArrayUtil.cs b/EasyTcp3/EasyTcp3/ClientUtils/LargeArrayUtil.cs
index 409d9ea..845376e 100644
--- a/EasyTcp3/EasyTcp3/ClientUtils/LargeArrayUtil.cs
+++ b/EasyTcp3/EasyTcp3/ClientUtils/LargeArrayUtil.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.IO.Compression;
namespace EasyTcp3.ClientUtils
{
@@ -14,14 +15,18 @@ public static class ArrayUtil
///
///
///
+ ///
/// determines whether prefix with length of the data is send
- public static void SendLargeArray(this EasyTcpClient client, byte[] array, bool sendLengthPrefix = true)
+ public static void SendLargeArray(this EasyTcpClient client, byte[] array, bool compression = false,
+ bool sendLengthPrefix = true)
{
- if(client?.BaseSocket == null) throw new Exception("Client is not connected");
-
+ if (client?.BaseSocket == null) throw new Exception("Client is not connected");
+
using var networkStream = client.Protocol.GetStream(client);
- if(sendLengthPrefix) networkStream.Write(BitConverter.GetBytes(array.Length));
- networkStream.Write(array);
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Compress) : networkStream;
+
+ if (sendLengthPrefix) dataStream.Write(BitConverter.GetBytes(array.Length), 0, 4);
+ dataStream.Write(array, 0, array.Length);
}
///
@@ -29,20 +34,24 @@ public static void SendLargeArray(this EasyTcpClient client, byte[] array, bool
/// Use this method only when not listening for incoming messages (In the OnReceive event)
///
///
+ ///
/// length of data, use prefix when 0
///
/// stream is not writable
- public static byte[] ReceiveLargeArray(this Message message, int count = 0, int bufferSize = 1024)
+ public static byte[] ReceiveLargeArray(this Message message, bool compression = false, int count = 0,
+ int bufferSize = 1024)
{
- if(message?.Client?.BaseSocket == null) throw new Exception("Client is not connected");
-
+ if (message?.Client?.BaseSocket == null) throw new Exception("Client is not connected");
+
using var networkStream = message.Client.Protocol.GetStream(message.Client);
+ using var dataStream =
+ compression ? new GZipStream(networkStream, CompressionMode.Decompress) : networkStream;
// Get length from stream
if (count == 0)
{
var length = new byte[4];
- networkStream.Read(length, 0, length.Length);
+ dataStream.Read(length, 0, length.Length);
count = BitConverter.ToInt32(length, 0);
}
@@ -50,7 +59,7 @@ public static byte[] ReceiveLargeArray(this Message message, int count = 0, int
int read, totalReceivedBytes = 0;
while (totalReceivedBytes < count &&
- (read = networkStream.Read(receivedArray, totalReceivedBytes,
+ (read = dataStream.Read(receivedArray, totalReceivedBytes,
Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
totalReceivedBytes += read;
return receivedArray;
diff --git a/EasyTcp3/EasyTcp3/ClientUtils/SendAndGetReplyUtil.cs b/EasyTcp3/EasyTcp3/ClientUtils/SendAndGetReplyUtil.cs
index fb96177..bf6ca1f 100644
--- a/EasyTcp3/EasyTcp3/ClientUtils/SendAndGetReplyUtil.cs
+++ b/EasyTcp3/EasyTcp3/ClientUtils/SendAndGetReplyUtil.cs
@@ -1,6 +1,7 @@
using System;
using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using EasyTcp3.EasyTcpPacketUtils;
namespace EasyTcp3.ClientUtils
@@ -34,6 +35,7 @@ public static Message SendAndGetReply(this EasyTcpClient client, TimeSpan? timeo
// Function is no longer used when signal is disposed, therefore ignore this warning
// ReSharper disable once AccessToDisposedClosure
signal.Set();
+ return Task.CompletedTask;
};
client.Send(data);
diff --git a/EasyTcp3/EasyTcp3/ClientUtils/StreamUtil.cs b/EasyTcp3/EasyTcp3/ClientUtils/StreamUtil.cs
index 06b6a1c..70aae62 100644
--- a/EasyTcp3/EasyTcp3/ClientUtils/StreamUtil.cs
+++ b/EasyTcp3/EasyTcp3/ClientUtils/StreamUtil.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.IO.Compression;
namespace EasyTcp3.ClientUtils
{
@@ -15,22 +16,25 @@ public static class StreamUtil
///
/// input stream
/// determines whether prefix with length of the data is send
+ ///
///
/// stream is not readable
- public static void SendStream(this EasyTcpClient client, Stream stream, bool sendLengthPrefix = true,
+ public static void SendStream(this EasyTcpClient client, Stream stream, bool compression = false, bool sendLengthPrefix = true,
int bufferSize = 1024)
{
if(client?.BaseSocket == null) throw new Exception("Client is not connected");
if (!stream.CanRead) throw new InvalidDataException("Stream is not readable");
using var networkStream = client.Protocol.GetStream(client);
- if (sendLengthPrefix) networkStream.Write(BitConverter.GetBytes(stream.Length));
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Compress) : networkStream;
+
+ if (sendLengthPrefix) dataStream.Write(BitConverter.GetBytes(stream.Length),0,8);
var buffer = new byte[bufferSize];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
- networkStream.Write(buffer, 0, read);
+ dataStream.Write(buffer, 0, read);
}
///
@@ -40,21 +44,23 @@ public static void SendStream(this EasyTcpClient client, Stream stream, bool sen
///
/// output stream for receiving data
/// length of data, use prefix when 0
+ ///
///
/// stream is not writable
- public static void ReceiveStream(this Message message, Stream stream, long count = 0, int bufferSize = 1024)
+ public static void ReceiveStream(this Message message, Stream stream, bool compression = false, long count = 0, int bufferSize = 1024)
{
if(message?.Client?.BaseSocket == null) throw new Exception("Client is not connected");
if (!stream.CanWrite) throw new InvalidDataException("Stream is not writable");
using var networkStream = message.Client.Protocol.GetStream(message.Client);
+ using var dataStream = compression ? new GZipStream(networkStream, CompressionMode.Decompress) : networkStream;
//Get length of stream
if (count == 0)
{
var length = new byte[8];
- networkStream.Read(length, 0, length.Length);
- count = BitConverter.ToInt64(length);
+ dataStream.Read(length, 0, length.Length);
+ count = BitConverter.ToInt64(length, 0);
}
var buffer = new byte[bufferSize];
@@ -62,7 +68,7 @@ public static void ReceiveStream(this Message message, Stream stream, long count
int read;
while (totalReceivedBytes < count &&
- (read = networkStream.Read(buffer, 0, (int)Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
+ (read = dataStream.Read(buffer, 0, (int)Math.Min(bufferSize, count - totalReceivedBytes))) > 0)
{
stream.Write(buffer, 0, read);
totalReceivedBytes += read;
diff --git a/EasyTcp3/EasyTcp3/EasyTcp3.csproj b/EasyTcp3/EasyTcp3/EasyTcp3.csproj
index af32d26..a73f918 100644
--- a/EasyTcp3/EasyTcp3/EasyTcp3.csproj
+++ b/EasyTcp3/EasyTcp3/EasyTcp3.csproj
@@ -1,7 +1,6 @@
- netstandard2.1
true
3.5.0
EasyTcp
@@ -14,5 +13,7 @@
EasyTcp
true
Socket Networking Tcp TcpClient TcpServer Server SimpleTcp EasyTcp AsyncTcp
+ 8
+ netstandard2.0;netstandard2.1
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3/EasyTcpClient.cs b/EasyTcp3/EasyTcp3/EasyTcpClient.cs
index c7762ee..a407b8a 100644
--- a/EasyTcp3/EasyTcp3/EasyTcpClient.cs
+++ b/EasyTcp3/EasyTcp3/EasyTcpClient.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
+using System.Threading.Tasks;
using EasyTcp3.Protocols;
using EasyTcp3.Protocols.Tcp;
@@ -33,7 +34,6 @@ public IEasyTcpProtocol Protocol
private IEasyTcpProtocol _protocol;
-
///
/// List with session variables
///
@@ -57,11 +57,6 @@ public Dictionary Session
public Func Deserialize = (b, t) =>
throw new Exception("Assign a function to deserialize first before using serialisation");
- ///
- /// Buffer with received data
- ///
- public byte[] Buffer;
-
///
/// Event that is fired when client connected to remote host
///
@@ -73,10 +68,20 @@ public Dictionary Session
public event EventHandler OnDisconnect;
///
- /// Event that is fired when client receives data from remote host
+ /// Async event that is fired when client receives data from remote host
///
public event EventHandler OnDataReceive;
+ ///
+ /// Event that is fired when client receives data from remote host
+ ///
+ public event OnDataReceiveAsyncDelegate OnDataReceiveAsync;
+
+ ///
+ /// Delegate type for OnDataReceiveAsync
+ ///
+ public delegate Task OnDataReceiveAsyncDelegate(object sender, Message message);
+
///
/// Event that is fired when client sends any data to remote host
///
@@ -96,12 +101,13 @@ public Dictionary Session
/// Fire the OnDisconnect event
///
public void FireOnDisconnect() => OnDisconnect?.Invoke(this, this);
-
+
///
/// Fire the OnDataSend event
///
- ///
- public void FireOnDataSend(Message message) => OnDataSend?.Invoke(this, message);
+ ///
+ ///
+ public void FireOnDataSend(byte[] data, EasyTcpClient client) => OnDataSend?.Invoke(this, new Message(data, client));
///
/// Fire the OnError event,
@@ -118,12 +124,16 @@ public void FireOnError(Exception exception)
/// Fire the OnDataReceive event
///
/// received message
- public void FireOnDataReceiveEvent(Message message) => OnDataReceive?.Invoke(this, message);
+ public async Task FireOnDataReceiveEvent(Message message)
+ {
+ if (OnDataReceiveAsync != null) await OnDataReceiveAsync.Invoke(this, message);
+ OnDataReceive?.Invoke(this, message);
+ }
///
/// Execute custom action when receiving data
///
- public Action DataReceiveHandler;
+ public Func DataReceiveHandler;
///
/// Set DataReceiveHandler back to default behavior (calling OnDataReceive)
diff --git a/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/EasyTcpPacket.cs b/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/EasyTcpPacket.cs
new file mode 100644
index 0000000..a1207e0
--- /dev/null
+++ b/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/EasyTcpPacket.cs
@@ -0,0 +1,17 @@
+namespace EasyTcp3.EasyTcpPacketUtils
+{
+ ///
+ ///
+ public static class EasyTcpPacket
+ {
+ ///
+ /// Create package from byte array
+ ///
+ /// data of new package
+ /// compress data using GZIP if set to true
+ /// package type
+ /// new package
+ public static T From(byte[] data, bool compression = false) where T : IEasyTcpPacket, new()
+ => compression ? new T {Data = data}.Compress() : new T {Data = data};
+ }
+}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/IEasyTcpPacket.cs b/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/IEasyTcpPacket.cs
index 3efb867..19017d7 100644
--- a/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/IEasyTcpPacket.cs
+++ b/EasyTcp3/EasyTcp3/EasyTcpPacketUtils/IEasyTcpPacket.cs
@@ -11,15 +11,5 @@ public interface IEasyTcpPacket
/// set => create class from byte[]
///
public byte[] Data { get; set; }
-
- ///
- /// Create package from byte array
- ///
- /// data of new package
- /// compress data using GZIP if set to true
- /// package type
- /// new package
- public static T From(byte[] data, bool compression = false) where T : IEasyTcpPacket, new()
- => compression ? new T {Data = data}.Compress() : new T {Data = data};
}
}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3/Message.cs b/EasyTcp3/EasyTcp3/Message.cs
index c24efec..ea23fdf 100644
--- a/EasyTcp3/EasyTcp3/Message.cs
+++ b/EasyTcp3/EasyTcp3/Message.cs
@@ -85,49 +85,49 @@ public Message(byte[] data, EasyTcpClient client = null)
/// Convert data to UShort
///
/// data as UShort
- public ushort ToUShort() => BitConverter.ToUInt16(Data);
+ public ushort ToUShort() => BitConverter.ToUInt16(Data, 0);
///
/// Convert data to Short
///
/// data as Short
- public short ToShort() => BitConverter.ToInt16(Data);
+ public short ToShort() => BitConverter.ToInt16(Data, 0);
///
/// Convert data to UInt
///
/// data as UInt
- public uint ToUInt() => BitConverter.ToUInt32(Data);
+ public uint ToUInt() => BitConverter.ToUInt32(Data, 0);
///
/// Convert data to Int
///
/// data as Int
- public int ToInt() => BitConverter.ToInt16(Data);
+ public int ToInt() => BitConverter.ToInt16(Data, 0);
///
/// Convert data to ULong
///
/// data as ULong
- public ulong ToULong() => BitConverter.ToUInt64(Data);
+ public ulong ToULong() => BitConverter.ToUInt64(Data, 0);
///
/// Convert data to Long
///
/// data as Long
- public long ToLong() => BitConverter.ToInt64(Data);
+ public long ToLong() => BitConverter.ToInt64(Data, 0);
///
/// Convert data to Double
///
/// data as Double
- public double ToDouble() => BitConverter.ToDouble(Data);
+ public double ToDouble() => BitConverter.ToDouble(Data, 0);
///
/// Convert data to Bool
///
/// data as Bool
- public bool ToBool() => BitConverter.ToBoolean(Data);
+ public bool ToBool() => BitConverter.ToBoolean(Data, 0);
///
/// Convert data to String
@@ -147,7 +147,7 @@ public Message(byte[] data, EasyTcpClient client = null)
///
/// Packet type
/// data as custom IEasyTcpPacket
- public T ToPacket() where T : IEasyTcpPacket, new() => IEasyTcpPacket.From(Data);
+ public T ToPacket() where T : IEasyTcpPacket, new() => EasyTcpPacket.From(Data);
///
/// Deserialize object from byte[]
diff --git a/EasyTcp3/EasyTcp3/Protocols/IEasyTcpProtocol.cs b/EasyTcp3/EasyTcp3/Protocols/IEasyTcpProtocol.cs
index bf2a472..ac2a877 100644
--- a/EasyTcp3/EasyTcp3/Protocols/IEasyTcpProtocol.cs
+++ b/EasyTcp3/EasyTcp3/Protocols/IEasyTcpProtocol.cs
@@ -51,36 +51,24 @@ public interface IEasyTcpProtocol : ICloneable, IDisposable
///
public void SendMessage(EasyTcpClient client, byte[] message);
- /*
- * Optional
- */
-
///
/// Get receiving/sending stream
///
///
- public Stream GetStream(EasyTcpClient client) => new NetworkStream(client.BaseSocket);
-
+ public Stream GetStream(EasyTcpClient client);
+
///
/// Method that is triggered when client connects
/// Default behavior is starting listening for incoming data
///
///
- public bool OnConnect(EasyTcpClient client)
- {
- EnsureDataReceiverIsRunning(client);
- return true;
- }
+ public bool OnConnect(EasyTcpClient client);
///
/// Method that is triggered when client connects to server
/// Default behavior is starting listening for incoming data
///
///
- public bool OnConnectServer(EasyTcpClient client)
- {
- EnsureDataReceiverIsRunning(client);
- return true;
- }
+ public bool OnConnectServer(EasyTcpClient client);
}
}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3/Protocols/Tcp/DefaultTcpProtocol.cs b/EasyTcp3/EasyTcp3/Protocols/Tcp/DefaultTcpProtocol.cs
index 82a69bc..5f0be57 100644
--- a/EasyTcp3/EasyTcp3/Protocols/Tcp/DefaultTcpProtocol.cs
+++ b/EasyTcp3/EasyTcp3/Protocols/Tcp/DefaultTcpProtocol.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Net.Sockets;
+using System.Threading.Tasks;
using EasyTcp3.Server;
namespace EasyTcp3.Protocols.Tcp
@@ -10,6 +11,11 @@ namespace EasyTcp3.Protocols.Tcp
///
public abstract class DefaultTcpProtocol : IEasyTcpProtocol
{
+ ///
+ /// AsyncEventArgs with received data
+ ///
+ public SocketAsyncEventArgs ReceiveBuffer;
+
///
/// Default socket for protocol
///
@@ -24,8 +30,15 @@ public virtual Socket GetSocket(AddressFamily addressFamily) =>
///
public virtual void StartAcceptingClients(EasyTcpServer server)
{
- server.BaseSocket.Listen(50000);
- server.BaseSocket.BeginAccept(OnConnectCallback, server);
+ if (server.AcceptArgs == null)
+ {
+ server.BaseSocket.Listen(50000);
+ server.AcceptArgs = new SocketAsyncEventArgs {UserToken = server};
+ server.AcceptArgs.Completed += (_, ar) => OnConnectCallback(ar);
+ }
+
+ server.AcceptArgs.AcceptSocket = null;
+ if (!server.BaseSocket.AcceptAsync(server.AcceptArgs)) OnConnectCallback(server.AcceptArgs);
}
///
@@ -34,10 +47,21 @@ public virtual void StartAcceptingClients(EasyTcpServer server)
///
public virtual void EnsureDataReceiverIsRunning(EasyTcpClient client)
{
- if(IsListening) return;
+ if (IsListening) return;
IsListening = true;
- client.BaseSocket.BeginReceive(client.Buffer = new byte[BufferSize], 0,
- client.Buffer.Length, SocketFlags.None, OnReceiveCallback, client);
+
+ var protocol = (DefaultTcpProtocol) client.Protocol;
+
+ if (protocol.ReceiveBuffer == null)
+ {
+ protocol.ReceiveBuffer = new SocketAsyncEventArgs {UserToken = client};
+ protocol.ReceiveBuffer.Completed += (_, ar) => OnReceiveCallback(ar);
+ }
+
+ var bufferSize = BufferSize;
+ protocol.ReceiveBuffer.SetBuffer(new byte[bufferSize], 0, bufferSize);
+ if (!client.BaseSocket.ReceiveAsync(protocol.ReceiveBuffer)) OnReceiveCallback(protocol.ReceiveBuffer);
+
}
///
@@ -58,12 +82,36 @@ public virtual void SendMessage(EasyTcpClient client, byte[] message)
if (client?.BaseSocket == null || !client.BaseSocket.Connected)
throw new Exception("Could not send data: Client not connected or null");
- client.FireOnDataSend(new Message(message, client));
- client.BaseSocket.BeginSend(message, 0, message.Length, SocketFlags.None, ar =>
- {
- var socket = ar.AsyncState as Socket;
- socket?.EndSend(ar);
- }, client.BaseSocket);
+ client.FireOnDataSend(message, client);
+ client.BaseSocket.Send(message, SocketFlags.None);
+ }
+
+ ///
+ /// Get receiving/sending stream
+ ///
+ ///
+ public Stream GetStream(EasyTcpClient client) => new NetworkStream(client.BaseSocket);
+
+ ///
+ /// Method that is triggered when client connects
+ /// Default behavior is starting listening for incoming data
+ ///
+ ///
+ public bool OnConnect(EasyTcpClient client)
+ {
+ EnsureDataReceiverIsRunning(client);
+ return true;
+ }
+
+ ///
+ /// Method that is triggered when client connects to server
+ /// Default behavior is starting listening for incoming data
+ ///
+ ///
+ public bool OnConnectServer(EasyTcpClient client)
+ {
+ EnsureDataReceiverIsRunning(client);
+ return true;
}
///
@@ -78,6 +126,7 @@ public virtual void SendMessage(EasyTcpClient client, byte[] message)
///
public virtual void Dispose()
{
+ ReceiveBuffer?.Dispose();
}
/*
@@ -95,7 +144,7 @@ public virtual void Dispose()
/// received data, has size of clients buffer
/// amount of received bytes
///
- public abstract void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client);
+ public abstract Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client);
/*
* Internal methods
@@ -121,24 +170,25 @@ protected virtual void HandleDisconnect(EasyTcpClient client)
/// Fired when new client connects
///
///
- protected virtual void OnConnectCallback(IAsyncResult ar)
+ protected virtual void OnConnectCallback(SocketAsyncEventArgs ar)
{
- var server = ar.AsyncState as EasyTcpServer;
+ var server = ar.UserToken as EasyTcpServer;
if (server?.BaseSocket == null || !server.IsRunning) return;
try
{
- var client = new EasyTcpClient(server.BaseSocket.EndAccept(ar),
+ var client = new EasyTcpClient(ar.AcceptSocket,
(IEasyTcpProtocol) server.Protocol.Clone())
{
Serialize = server.Serialize,
Deserialize = server.Deserialize
};
- client.OnDataReceive += (_, message) => server.FireOnDataReceive(message);
+ client.OnDataReceiveAsync += async (_, message) => await server.FireOnDataReceive(message);
client.OnDataSend += (_, message) => server.FireOnDataSend(message);
client.OnDisconnect += (_, c) => server.FireOnDisconnect(c);
client.OnError += (_, exception) => server.FireOnError(exception);
- server.BaseSocket.BeginAccept(OnConnectCallback, server);
+
+ StartAcceptingClients(server);
if (!client.Protocol.OnConnectServer(client)) return;
server.FireOnConnect(client);
@@ -157,20 +207,18 @@ protected virtual void OnConnectCallback(IAsyncResult ar)
/// Fired when new data is received
///
///
- protected virtual void OnReceiveCallback(IAsyncResult ar)
+ protected virtual async void OnReceiveCallback(SocketAsyncEventArgs ar)
{
- var client = ar.AsyncState as EasyTcpClient;
+ var client = ar.UserToken as EasyTcpClient;
if (client == null) return;
IsListening = false;
try
{
- int receivedBytes = client.BaseSocket.EndReceive(ar, out SocketError socketErr);
- if (receivedBytes != 0 || socketErr != SocketError.Success)
+ if (ar.BytesTransferred != 0)
{
- DataReceive(client.Buffer, receivedBytes, client);
- if (client.BaseSocket == null)
- HandleDisconnect(client); // Check if client is disposed by DataReceive
+ await DataReceive(ar.Buffer, ar.BytesTransferred, client);
+ if (client.BaseSocket == null) HandleDisconnect(client); // Check if client is disposed by DataReceive
else EnsureDataReceiverIsRunning(client);
}
else HandleDisconnect(client);
diff --git a/EasyTcp3/EasyTcp3/Protocols/Tcp/DelimiterProtocol.cs b/EasyTcp3/EasyTcp3/Protocols/Tcp/DelimiterProtocol.cs
index fd5d4ec..c07eb1e 100644
--- a/EasyTcp3/EasyTcp3/Protocols/Tcp/DelimiterProtocol.cs
+++ b/EasyTcp3/EasyTcp3/Protocols/Tcp/DelimiterProtocol.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Threading.Tasks;
namespace EasyTcp3.Protocols.Tcp
{
@@ -103,7 +104,7 @@ public override byte[] CreateMessage(params byte[][] data)
/// received data, has size of clients buffer
/// amount of received bytes
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
byte receivedByte = data[0]; // Size of buffer is always 1
ReceivedBytes.Add(receivedByte);
@@ -119,7 +120,7 @@ public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient c
byte[] receivedData = AutoRemoveDelimiter
? ReceivedBytes.Take(receivedBytesLength).ToArray() // Remove delimiter from message
: ReceivedBytes.ToArray();
- client.DataReceiveHandler(new Message(receivedData, client));
+ await client.DataReceiveHandler(new Message(receivedData, client));
ReceivedBytes.Clear();
}
}
diff --git a/EasyTcp3/EasyTcp3/Protocols/Tcp/NoneProtocol.cs b/EasyTcp3/EasyTcp3/Protocols/Tcp/NoneProtocol.cs
index 2c82a98..dd5bcc5 100644
--- a/EasyTcp3/EasyTcp3/Protocols/Tcp/NoneProtocol.cs
+++ b/EasyTcp3/EasyTcp3/Protocols/Tcp/NoneProtocol.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
namespace EasyTcp3.Protocols.Tcp
{
@@ -64,11 +65,11 @@ public override byte[] CreateMessage(params byte[][] data)
/// received data, has size of clients buffer
/// amount of received bytes
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
byte[] receivedData = new byte[receivedBytes];
Buffer.BlockCopy(data,0,receivedData,0,receivedBytes);
- client.DataReceiveHandler(new Message(receivedData, client));
+ await client.DataReceiveHandler(new Message(receivedData, client));
}
}
}
\ No newline at end of file
diff --git a/EasyTcp3/EasyTcp3/Protocols/Tcp/PrefixLengthProtocol.cs b/EasyTcp3/EasyTcp3/Protocols/Tcp/PrefixLengthProtocol.cs
index b89548d..a0860fa 100644
--- a/EasyTcp3/EasyTcp3/Protocols/Tcp/PrefixLengthProtocol.cs
+++ b/EasyTcp3/EasyTcp3/Protocols/Tcp/PrefixLengthProtocol.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
namespace EasyTcp3.Protocols.Tcp
{
@@ -66,17 +67,17 @@ public override byte[] CreateMessage(params byte[][] data)
///
/// ignored
///
- public override void DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
+ public override async Task DataReceive(byte[] data, int receivedBytes, EasyTcpClient client)
{
if (!(ReceivingLength = !ReceivingLength))
{
- BufferSize = BitConverter.ToUInt16(client.Buffer, 0);
+ BufferSize = BitConverter.ToUInt16(data, 0);
if (BufferSize == 0) client.Dispose();
}
else
{
BufferSize = 2;
- client.DataReceiveHandler(new Message(client.Buffer, client));
+ await client.DataReceiveHandler(new Message(data, client));
}
}
}
diff --git a/EasyTcp3/EasyTcp3/Server/EasyTcpServer.cs b/EasyTcp3/EasyTcp3/Server/EasyTcpServer.cs
index 2759015..a34f73e 100644
--- a/EasyTcp3/EasyTcp3/Server/EasyTcpServer.cs
+++ b/EasyTcp3/EasyTcp3/Server/EasyTcpServer.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
+using System.Threading.Tasks;
using EasyTcp3.Protocols;
using EasyTcp3.Protocols.Tcp;
@@ -17,6 +18,11 @@ public class EasyTcpServer : IDisposable
/// BaseSocket of server
///
public Socket BaseSocket { get; protected internal set; }
+
+ ///
+ /// AsyncEventArgs used to accept new sockets
+ ///
+ public SocketAsyncEventArgs AcceptArgs;
///
/// Protocol for server, protocol determines all behavior of this server
@@ -89,6 +95,16 @@ public IEasyTcpProtocol Protocol
/// Event that is fired when server receives data
///
public event EventHandler OnDataReceive;
+
+ ///
+ /// Event that is fired when client receives data from remote host
+ ///
+ public event OnDataReceiveAsyncDelegate OnDataReceiveAsync;
+
+ ///
+ /// Delegate type for OnDataReceiveAsync
+ ///
+ public delegate Task OnDataReceiveAsyncDelegate(object sender, Message message);
///
/// Event that is fired when server sends data to a client
@@ -120,8 +136,12 @@ public void FireOnDisconnect(EasyTcpClient client)
/// Fire the OnDataReceive event
///
///
- public void FireOnDataReceive(Message message) => OnDataReceive?.Invoke(this, message);
-
+ public async Task FireOnDataReceive(Message message)
+ {
+ if (OnDataReceiveAsync != null) await OnDataReceiveAsync.Invoke(this, message);
+ OnDataReceive?.Invoke(this, message);
+ }
+
///
/// Fire the OnDataSend event
///
@@ -157,6 +177,7 @@ public void Dispose()
}
UnsafeConnectedClients.Clear();
+ AcceptArgs?.Dispose();
Protocol?.Dispose();
BaseSocket.Dispose();
BaseSocket = null;
diff --git a/README.md b/README.md
index 9a41f2b..510323a 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,22 @@
-# EasyTcp
+# Features
+- Simple and Easy to use
+- High performance (~430.000 round trips/second)*
+- Very lightweight (use only what you need)
+- Async support
+- Actions wich make creating API's realy simple (See EasyTcp.Actions)
+- Support for sending raw streams/very large arrays
+- Serialistaion and compression
+- Different kinds of framing
+- MIT license
+- Unit tested (~250 unit tests)
+
+\* Tested on local machine(linux, ryzen 7) with clients and server running under the same process. See EasyTcp.Examples/SpeedTest/ThroughputTest.cs
+
+# Packages
+## EasyTcp
EasyTcp3 is a package that makes creating tcp servers and clients simple.
It is very fast, simple, supports framing, serialisation, disconnect detection, event handlers and more.
See the [EasyTcp.Examples](https://github.com/Job79/EasyTcp/tree/master/EasyTcp3/EasyTcp3.Examples) folder for documentation.
@@ -30,7 +45,7 @@ if(!client.Connect("127.0.0.1", PORT)) return;
client.Send("Hello server");
```
-# EasyTcp.Actions
+## EasyTcp.Actions
EasyTcp.Actions adds support to EasyTcp for triggering functions based on received data.
It does this without giving up (noticeable) performance, and makes creating big servers/clients easy.
See the [EasyTcp.Examples](https://github.com/Job79/EasyTcp/tree/master/EasyTcp3/EasyTcp3.Examples) folder for documentation.
@@ -64,7 +79,7 @@ client.SendAction("ECHO","Hello me"); // Trigger the ECHO action server side
client.SendAction("BROADCAST","Hello everyone"); // Trigger the BROADCAST action server side
```
-# EasyTcp.Encryption
+## EasyTcp.Encryption
EasyTcp.Encryption adds ssl adn encryption support to EasyTcp.
See the [EasyTcp.Examples](https://github.com/Job79/EasyTcp/tree/master/EasyTcp3/EasyTcp3.Examples) folder for documentation.
```cs
@@ -91,6 +106,18 @@ using var client = new EasyTcpClient().UseEncryption(encrypter);
if(!client.Connect("127.0.0.1", PORT)) return;
client.Send("Hello encrypted server!"); // All data is automatically encrypted
```
+
+## EasyTcp.Logging
+EasyTcp.Logging adds support for logging of incoming/outgoing messages/connections and errors.
+```cs
+using var server = new EasyTcpServer().UseServerLogging(Console.WriteLine).Start(Port);
+
+using var client = new EasyTcpClient().UseClientLogging(Console.WriteLine);
+if(!client.Connect("127.0.0.1", Port)) return;
+client.Send("Hello server!");
+Console.ReadLine();
+```
+
# Contribution / Help / Questions / Feedback
Create a issue, pull request or send an email to jobse@pm.me