From b5b2d67b4d1c76fca584c4fe890e6b759a204c42 Mon Sep 17 00:00:00 2001 From: Filipe GOMES PEIXOTO Date: Sat, 17 Feb 2018 12:38:06 +0100 Subject: [PATCH] Add NetClientConfiguration properties --- samples/SampleClient/MyClient.cs | 8 ++- samples/SampleClient/Program.cs | 6 +- samples/SampleServer/Program.cs | 4 +- src/Ether.Network/Client/INetClient.cs | 5 ++ src/Ether.Network/Client/NetClient.cs | 59 +++++++++------- .../Client/NetClientConfiguration.cs | 69 ++++++++++++++++++- src/Ether.Network/Server/NetServer.cs | 7 +- .../Contexts/Echo/MyEchoClient.cs | 8 ++- 8 files changed, 125 insertions(+), 41 deletions(-) diff --git a/samples/SampleClient/MyClient.cs b/samples/SampleClient/MyClient.cs index 985a2f1..df0edb6 100644 --- a/samples/SampleClient/MyClient.cs +++ b/samples/SampleClient/MyClient.cs @@ -13,9 +13,11 @@ internal sealed class MyClient : NetClient /// /// /// - public MyClient(string host, int port, int bufferSize) - : base(host, port, bufferSize) + public MyClient(string host, int port, int bufferSize) { + this.Configuration.Host = host; + this.Configuration.Port = port; + this.Configuration.BufferSize = bufferSize; } /// @@ -33,7 +35,7 @@ public override void HandleMessage(INetPacketStream packet) /// protected override void OnConnected() { - Console.WriteLine("Connected to {0}", this.Socket.RemoteEndPoint.ToString()); + Console.WriteLine("Connected to {0}", this.Socket.RemoteEndPoint); } /// diff --git a/samples/SampleClient/Program.cs b/samples/SampleClient/Program.cs index 2717186..554f336 100644 --- a/samples/SampleClient/Program.cs +++ b/samples/SampleClient/Program.cs @@ -5,9 +5,9 @@ namespace SampleClient { - class Program + internal class Program { - static void Main(string[] args) + private static void Main() { var client = new MyClient("127.0.0.1", 4444, 512); client.Connect(); @@ -39,7 +39,7 @@ static void Main(string[] args) } i++; - Thread.Sleep(5); + Thread.Sleep(50); } } catch (Exception e) diff --git a/samples/SampleServer/Program.cs b/samples/SampleServer/Program.cs index 29071d0..eb36c55 100644 --- a/samples/SampleServer/Program.cs +++ b/samples/SampleServer/Program.cs @@ -2,9 +2,9 @@ namespace SampleServer { - class Program + internal class Program { - static void Main(string[] args) + private static void Main() { Console.Title = "Ether.Network Server"; diff --git a/src/Ether.Network/Client/INetClient.cs b/src/Ether.Network/Client/INetClient.cs index 7324636..1ff9ee2 100644 --- a/src/Ether.Network/Client/INetClient.cs +++ b/src/Ether.Network/Client/INetClient.cs @@ -17,6 +17,11 @@ public interface INetClient : IDisposable /// Gets the connected state. /// bool IsConnected { get; } + + /// + /// Gets the running state. + /// + bool IsRunning { get; } /// /// Connects to a remote server. diff --git a/src/Ether.Network/Client/NetClient.cs b/src/Ether.Network/Client/NetClient.cs index 98212b5..cf25db5 100644 --- a/src/Ether.Network/Client/NetClient.cs +++ b/src/Ether.Network/Client/NetClient.cs @@ -18,10 +18,7 @@ namespace Ether.Network.Client public abstract class NetClient : NetUser, INetClient { private static readonly IPacketProcessor DefaultPacketProcessor = new NetPacketProcessor(); - - private readonly IPEndPoint _ipEndPoint; - private readonly SocketAsyncEventArgs _socketReceiveArgs; - private readonly SocketAsyncEventArgs _socketSendArgs; + private readonly AutoResetEvent _autoConnectEvent; private readonly AutoResetEvent _autoSendEvent; private readonly BlockingCollection _sendingQueue; @@ -32,29 +29,31 @@ public abstract class NetClient : NetUser, INetClient private readonly CancellationToken _cancelToken; private bool _isDisposed; + private SocketAsyncEventArgs _socketReceiveArgs; + private SocketAsyncEventArgs _socketSendArgs; /// /// Gets the packet processor. /// protected virtual IPacketProcessor PacketProcessor => DefaultPacketProcessor; + /// + public bool IsConnected => this.Socket != null && this.Socket.Connected; + + /// + public bool IsRunning { get; private set; } + /// - /// Gets the connected state. + /// Gets the configuration. /// - public bool IsConnected => this.Socket != null && this.Socket.Connected; + protected NetClientConfiguration Configuration { get; } /// /// Creates a new instance. /// - /// Remote host or ip - /// Remote port - /// Buffer size - protected NetClient(string host, int port, int bufferSize) + protected NetClient() { - this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - this._ipEndPoint = NetUtils.CreateIpEndPoint(host, port); - this._socketSendArgs = NetUtils.CreateSocketAsync(this.Socket, this.IO_Completed); - this._socketReceiveArgs = NetUtils.CreateSocketAsync(this, this.IO_Completed, bufferSize); + this.Configuration = new NetClientConfiguration(this); this._autoConnectEvent = new AutoResetEvent(false); this._autoSendEvent = new AutoResetEvent(false); this._sendingQueue = new BlockingCollection(); @@ -68,11 +67,18 @@ protected NetClient(string host, int port, int bufferSize) /// public void Connect() { + if (this.IsRunning) + throw new InvalidOperationException("Client is already running"); + if (this.IsConnected) throw new InvalidOperationException("Client is already connected to remote."); - var connectSocket = NetUtils.CreateSocketAsync(this.Socket, this.IO_Completed); - connectSocket.RemoteEndPoint = this._ipEndPoint; + this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + this._socketSendArgs = NetUtils.CreateSocketAsync(this.Socket, this.IO_Completed); + this._socketReceiveArgs = NetUtils.CreateSocketAsync(this, this.IO_Completed, this.Configuration.BufferSize); + + SocketAsyncEventArgs connectSocket = NetUtils.CreateSocketAsync(this.Socket, this.IO_Completed); + connectSocket.RemoteEndPoint = NetUtils.CreateIpEndPoint(this.Configuration.Host, this.Configuration.Port); if (this.Socket.ConnectAsync(connectSocket)) this._autoConnectEvent.WaitOne(); @@ -85,7 +91,8 @@ public void Connect() this._sendingQueueWorker.Start(); this._receivingQueueWorker.Start(); this.Token.Socket = this.Socket; - this.Token.MessageHandler = data => this._receivingQueue.Add(data); + this.Token.MessageHandler = data => this._receivingQueue.Add(data, this._cancelToken); + this.IsRunning = true; if (!this.Socket.ReceiveAsync(this._socketReceiveArgs)) this.ProcessReceive(this._socketReceiveArgs); @@ -100,10 +107,17 @@ public void Disconnect() this.Socket.Close(); #else this.Socket.Shutdown(SocketShutdown.Both); - this.Socket.Dispose(); #endif + this.Socket.Dispose(); + this.Socket = null; } + this._socketSendArgs?.Dispose(); + this._socketSendArgs = null; + this._socketReceiveArgs?.Dispose(); + this._socketReceiveArgs = null; + + this.IsRunning = false; this._cancelTokenSource.Cancel(false); this.OnDisconnected(); } @@ -114,7 +128,7 @@ public override void Send(INetPacketStream packet) if (!this.IsConnected) throw new SocketException(); - this._sendingQueue.Add(packet.Buffer); + this._sendingQueue.Add(packet.Buffer, this._cancelToken); } /// @@ -192,7 +206,7 @@ private void ProcessReceiveQueue() { using (INetPacketStream packet = this.PacketProcessor.CreatePacket(packetData)) this.HandleMessage(packet); - }); + }, this._cancelToken); } catch (Exception e) { @@ -212,9 +226,8 @@ private void ProcessReceive(SocketAsyncEventArgs e) { if (e.BytesTransferred <= 0 || !(e.UserToken is NetUser user)) return; - - IAsyncUserToken token = user.Token; - SocketAsyncUtils.ReceiveData(e, token, this.PacketProcessor); + + SocketAsyncUtils.ReceiveData(e, user.Token, this.PacketProcessor); if (!user.Socket.ReceiveAsync(e)) this.ProcessReceive(e); diff --git a/src/Ether.Network/Client/NetClientConfiguration.cs b/src/Ether.Network/Client/NetClientConfiguration.cs index 5662430..f786fbe 100644 --- a/src/Ether.Network/Client/NetClientConfiguration.cs +++ b/src/Ether.Network/Client/NetClientConfiguration.cs @@ -1,6 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Net; +using Ether.Network.Exceptions; +using Ether.Network.Utils; namespace Ether.Network.Client { @@ -9,5 +9,68 @@ namespace Ether.Network.Client /// public sealed class NetClientConfiguration { + private readonly INetClient _client; + private int _port; + private int _bufferSize; + private string _host; + + /// + /// Gets or sets the port. + /// + public int Port + { + get => this._port; + set => this.SetValue(ref this._port, value); + } + + /// + /// Gets or sets the buffer size. + /// + public int BufferSize + { + get => this._bufferSize; + set => this.SetValue(ref this._bufferSize, value); + } + + /// + /// Gets or sets the connecting host. + /// + public string Host + { + get => this._host; + set => this.SetValue(ref this._host, value); + } + + /// + /// Gets the listening address. + /// + internal IPAddress Address => NetUtils.GetIpAddress(this._host); + + /// + /// Creates a new instance. + /// + /// + internal NetClientConfiguration(INetClient client) + { + this._client = client; + this._bufferSize = 1024; + this._port = 0; + this._host = null; + } + + /// + /// Set the value of a property passed as reference. + /// + /// Type + /// + /// + private void SetValue(ref T container, T value) + { + if (this._client != null && this._client.IsRunning) + throw new EtherConfigurationException("Cannot change configuration once the client is running."); + + if (!Equals(container, value)) + container = value; + } } } diff --git a/src/Ether.Network/Server/NetServer.cs b/src/Ether.Network/Server/NetServer.cs index 25d72a4..9671515 100644 --- a/src/Ether.Network/Server/NetServer.cs +++ b/src/Ether.Network/Server/NetServer.cs @@ -306,11 +306,10 @@ private void ProcessReceive(SocketAsyncEventArgs e) { if (!(e.UserToken is NetUser connection)) return; + + SocketAsyncUtils.ReceiveData(e, connection.Token, this.PacketProcessor); - IAsyncUserToken token = connection.Token; - SocketAsyncUtils.ReceiveData(e, token, this.PacketProcessor); - - if (!token.Socket.ReceiveAsync(e)) + if (!connection.Socket.ReceiveAsync(e)) this.ProcessReceive(e); } else diff --git a/test/Ether.Network.Tests/Contexts/Echo/MyEchoClient.cs b/test/Ether.Network.Tests/Contexts/Echo/MyEchoClient.cs index ec5fd0a..b9343fe 100644 --- a/test/Ether.Network.Tests/Contexts/Echo/MyEchoClient.cs +++ b/test/Ether.Network.Tests/Contexts/Echo/MyEchoClient.cs @@ -19,14 +19,16 @@ public ICollection SendedData { this._sendedData.Sort(StringComparer.CurrentCulture); return this._sendedData; - } + } } public bool ConnectedToServer { get; private set; } - public MyEchoClient(string host, int port, int bufferSize) - : base(host, port, bufferSize) + public MyEchoClient(string host, int port, int bufferSize) { + this.Configuration.Host = host; + this.Configuration.Port = port; + this.Configuration.BufferSize = bufferSize; this._sendedData = new List(); this._random = new Random(); }