diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI.sln b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI.sln new file mode 100644 index 0000000..3bea166 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MossbauerLab.TinyTcpServer.MnGUI", "MossbauerLab.TinyTcpServer.MnGUI\MossbauerLab.TinyTcpServer.MnGUI.csproj", "{ECA495EA-1125-4FFC-BC2A-54EA06C74D80}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ECA495EA-1125-4FFC-BC2A-54EA06C74D80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECA495EA-1125-4FFC-BC2A-54EA06C74D80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECA495EA-1125-4FFC-BC2A-54EA06C74D80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECA495EA-1125-4FFC-BC2A-54EA06C74D80}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/App.config b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/App.config new file mode 100644 index 0000000..5ef2b32 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/App.config @@ -0,0 +1,33 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Data/ServerType.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Data/ServerType.cs new file mode 100644 index 0000000..c5798c9 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Data/ServerType.cs @@ -0,0 +1,12 @@ +using System; + +namespace MossbauerLab.TinyTcpServer.MnGUI.Data +{ + [Flags] + public enum ServerType + { + Echo, + Time, + Scripting // this option is for Server specifying with script + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/LogUtils/RichTextBoxAppender.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/LogUtils/RichTextBoxAppender.cs new file mode 100644 index 0000000..8bfbe75 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/LogUtils/RichTextBoxAppender.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using log4net.Appender; +using log4net.Core; + +namespace MossbauerLab.TinyTcpServer.MnGUI.LogUtils +{ + public class RichTextBoxAppender : MemoryAppender + { + public RichTextBoxAppender() + { + } + + public RichTextBoxAppender(RichTextBox richTextBox, Int32 maximumRichTextBoxLinesQuantity = DefaultRichTextBoxLines) + { + if(richTextBox == null) + throw new ArgumentNullException("richTextBox"); + _richTextBox = richTextBox; + _richTextBox.BackColor = Color.Black;; + _maximumRichTextBoxLinesQuantity = maximumRichTextBoxLinesQuantity; + } + + protected override void Append(LoggingEvent loggingEvent) + { + String logMessage = String.Format(LogMessageTemplate, loggingEvent.Level, loggingEvent.TimeStamp, loggingEvent.RenderedMessage); + _richTextBox.BeginInvoke(new Action(richTextBox => + { + richTextBox.AppendText(logMessage + Environment.NewLine); + richTextBox.Select(richTextBox.TextLength - logMessage.Length, logMessage.Length); + }), _richTextBox); + ApplyRichTextBoxFont(loggingEvent.Level); + if (_richTextBox.Lines.Length > _maximumRichTextBoxLinesQuantity) + _richTextBox.Clear(); + base.Append(loggingEvent); + } + + private void ApplyRichTextBoxFont(Level level) + { + _richTextBox.BeginInvoke(new Action(richTextBox => + { + Color richTextBoxTextColor = _richTextBoxLogsColors.ContainsKey(level) ? _richTextBoxLogsColors[level] : _defaultColor; + richTextBox.SelectionColor = richTextBoxTextColor; + richTextBox.SelectionFont = _defaultFont; + }), _richTextBox); + } + + private const Int32 DefaultRichTextBoxLines = 10000; + private const String DefaultFontFamily = "Times New Roman"; + private const float DefaultFontSize = 10.0f; + private const String LogMessageTemplate = "[{0}] [{1}] : {2}"; + + private readonly Font _defaultFont = new Font(DefaultFontFamily, DefaultFontSize, FontStyle.Bold); + private readonly Color _defaultColor = Color.Azure; + private readonly RichTextBox _richTextBox; + private readonly IDictionary _richTextBoxLogsColors = new Dictionary + { + {Level.Error, Color.OrangeRed}, + {Level.Warn, Color.Orange}, + {Level.Info, Color.LimeGreen}, + {Level.Debug, Color.Olive}, + {Level.All, Color.Azure} + }; + + private readonly Int32 _maximumRichTextBoxLinesQuantity; + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI.csproj b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI.csproj new file mode 100644 index 0000000..cf0cc1e --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI.csproj @@ -0,0 +1,100 @@ + + + + + Debug + AnyCPU + {ECA495EA-1125-4FFC-BC2A-54EA06C74D80} + WinExe + Properties + MossbauerLab.TinyTcpServer.MnGUI + MossbauerLab.TinyTcpServer.MnGUI + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\lib\log4net.dll + + + ..\lib\MossbauerLab.SimpleExtensions.dll + + + ..\lib\MossbauerLab.TinyTcpServer.Core.dll + + + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + \ No newline at end of file diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Program.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Program.cs new file mode 100644 index 0000000..b097cda --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Windows.Forms; +using MossbauerLab.TinyTcpServer.MnGUI.View.Forms; + +namespace MossbauerLab.TinyTcpServer.MnGUI +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(String[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/AssemblyInfo.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d74d6e9 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/AssemblyInfo.cs @@ -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("MossbauerLab.TinyTcpServer.MnGUI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("DDGroup")] +[assembly: AssemblyProduct("MossbauerLab.TinyTcpServer.MnGUI")] +[assembly: AssemblyCopyright("Copyright © DDGroup 2017")] +[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("cf1dcdc3-d468-4a81-ac05-48c5c175cae0")] + +// 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")] diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Resources.Designer.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Resources.Designer.cs new file mode 100644 index 0000000..fd85f61 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MossbauerLab.TinyTcpServer.MnGUI.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MossbauerLab.TinyTcpServer.MnGUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Resources.resx b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Settings.Designer.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Settings.Designer.cs new file mode 100644 index 0000000..ef7d3de --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MossbauerLab.TinyTcpServer.MnGUI.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Settings.settings b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/Factories/ServerFactory.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/Factories/ServerFactory.cs new file mode 100644 index 0000000..6deba98 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/Factories/ServerFactory.cs @@ -0,0 +1,21 @@ +using System; +using log4net; +using MossbauerLab.SimpleExtensions.Echo; +using MossbauerLab.SimpleExtensions.Time; +using MossbauerLab.TinyTcpServer.Core.Server; +using MossbauerLab.TinyTcpServer.MnGUI.Data; + +namespace MossbauerLab.TinyTcpServer.MnGUI.Factories +{ + public static class ServerFactory + { + public static ITcpServer Create(ServerType type, String ipAddress, UInt16 port, ILog logger = null, TcpServerConfig config = null) + { + if(type == ServerType.Echo) + return new EchoTcpServer(ipAddress, port, logger, false, config); + if(type == ServerType.Time) + return new TimeTcpServer(ipAddress, port, logger, false, config); + throw new NotImplementedException("Other types were not implemented"); + } + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.Designer.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.Designer.cs new file mode 100644 index 0000000..90eadae --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.Designer.cs @@ -0,0 +1,265 @@ +namespace MossbauerLab.TinyTcpServer.MnGUI.View.Forms +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this._startButton = new System.Windows.Forms.Button(); + this._stopButton = new System.Windows.Forms.Button(); + this._restartButton = new System.Windows.Forms.Button(); + this._logsGroupBox = new System.Windows.Forms.GroupBox(); + this._logsTextBox = new System.Windows.Forms.RichTextBox(); + this._clientsListBox = new System.Windows.Forms.ListBox(); + this._serverSettingsGroup = new System.Windows.Forms.GroupBox(); + this._logLevelComboBox = new System.Windows.Forms.ComboBox(); + this._logLevelLabel = new System.Windows.Forms.Label(); + this._serverParametersBox = new System.Windows.Forms.GroupBox(); + this._serverParametersView = new System.Windows.Forms.ListView(); + this._applyButton = new System.Windows.Forms.Button(); + this._serverTypeComboBox = new System.Windows.Forms.ComboBox(); + this._portTextBox = new System.Windows.Forms.TextBox(); + this._ipAddressComboBox = new System.Windows.Forms.ComboBox(); + this._serverTypeLabel = new System.Windows.Forms.Label(); + this._portLabel = new System.Windows.Forms.Label(); + this._ipAddressLabel = new System.Windows.Forms.Label(); + this._logsGroupBox.SuspendLayout(); + this._serverSettingsGroup.SuspendLayout(); + this._serverParametersBox.SuspendLayout(); + this.SuspendLayout(); + // + // _startButton + // + this._startButton.Location = new System.Drawing.Point(759, 352); + this._startButton.Name = "_startButton"; + this._startButton.Size = new System.Drawing.Size(75, 23); + this._startButton.TabIndex = 0; + this._startButton.Text = "Start"; + this._startButton.UseVisualStyleBackColor = true; + // + // _stopButton + // + this._stopButton.Location = new System.Drawing.Point(840, 352); + this._stopButton.Name = "_stopButton"; + this._stopButton.Size = new System.Drawing.Size(75, 23); + this._stopButton.TabIndex = 1; + this._stopButton.Text = "Stop"; + this._stopButton.UseVisualStyleBackColor = true; + // + // _restartButton + // + this._restartButton.Location = new System.Drawing.Point(921, 352); + this._restartButton.Name = "_restartButton"; + this._restartButton.Size = new System.Drawing.Size(75, 23); + this._restartButton.TabIndex = 2; + this._restartButton.Text = "Restart"; + this._restartButton.UseVisualStyleBackColor = true; + // + // _logsGroupBox + // + this._logsGroupBox.Controls.Add(this._logsTextBox); + this._logsGroupBox.Location = new System.Drawing.Point(12, 381); + this._logsGroupBox.Name = "_logsGroupBox"; + this._logsGroupBox.Size = new System.Drawing.Size(1000, 289); + this._logsGroupBox.TabIndex = 3; + this._logsGroupBox.TabStop = false; + this._logsGroupBox.Text = "Logs:"; + // + // _logsTextBox + // + this._logsTextBox.Location = new System.Drawing.Point(7, 20); + this._logsTextBox.Name = "_logsTextBox"; + this._logsTextBox.Size = new System.Drawing.Size(980, 253); + this._logsTextBox.TabIndex = 0; + this._logsTextBox.Text = ""; + // + // _clientsListBox + // + this._clientsListBox.FormattingEnabled = true; + this._clientsListBox.HorizontalScrollbar = true; + this._clientsListBox.Location = new System.Drawing.Point(624, 12); + this._clientsListBox.Name = "_clientsListBox"; + this._clientsListBox.Size = new System.Drawing.Size(375, 329); + this._clientsListBox.TabIndex = 4; + // + // _serverSettingsGroup + // + this._serverSettingsGroup.Controls.Add(this._logLevelComboBox); + this._serverSettingsGroup.Controls.Add(this._logLevelLabel); + this._serverSettingsGroup.Controls.Add(this._serverParametersBox); + this._serverSettingsGroup.Controls.Add(this._applyButton); + this._serverSettingsGroup.Controls.Add(this._serverTypeComboBox); + this._serverSettingsGroup.Controls.Add(this._portTextBox); + this._serverSettingsGroup.Controls.Add(this._ipAddressComboBox); + this._serverSettingsGroup.Controls.Add(this._serverTypeLabel); + this._serverSettingsGroup.Controls.Add(this._portLabel); + this._serverSettingsGroup.Controls.Add(this._ipAddressLabel); + this._serverSettingsGroup.Location = new System.Drawing.Point(12, 12); + this._serverSettingsGroup.Name = "_serverSettingsGroup"; + this._serverSettingsGroup.Size = new System.Drawing.Size(597, 363); + this._serverSettingsGroup.TabIndex = 5; + this._serverSettingsGroup.TabStop = false; + this._serverSettingsGroup.Text = "Server settings"; + // + // _logLevelComboBox + // + this._logLevelComboBox.FormattingEnabled = true; + this._logLevelComboBox.Location = new System.Drawing.Point(96, 175); + this._logLevelComboBox.Name = "_logLevelComboBox"; + this._logLevelComboBox.Size = new System.Drawing.Size(121, 21); + this._logLevelComboBox.TabIndex = 9; + // + // _logLevelLabel + // + this._logLevelLabel.AutoSize = true; + this._logLevelLabel.Location = new System.Drawing.Point(19, 183); + this._logLevelLabel.Name = "_logLevelLabel"; + this._logLevelLabel.Size = new System.Drawing.Size(57, 13); + this._logLevelLabel.TabIndex = 8; + this._logLevelLabel.Text = "Log Level:"; + // + // _serverParametersBox + // + this._serverParametersBox.Controls.Add(this._serverParametersView); + this._serverParametersBox.Location = new System.Drawing.Point(230, 21); + this._serverParametersBox.Name = "_serverParametersBox"; + this._serverParametersBox.Size = new System.Drawing.Size(350, 330); + this._serverParametersBox.TabIndex = 7; + this._serverParametersBox.TabStop = false; + this._serverParametersBox.Text = "Server Parameters"; + // + // _serverParametersView + // + this._serverParametersView.Location = new System.Drawing.Point(16, 21); + this._serverParametersView.Name = "_serverParametersView"; + this._serverParametersView.Size = new System.Drawing.Size(317, 287); + this._serverParametersView.TabIndex = 0; + this._serverParametersView.UseCompatibleStateImageBehavior = false; + this._serverParametersView.View = System.Windows.Forms.View.List; + // + // _applyButton + // + this._applyButton.Location = new System.Drawing.Point(142, 212); + this._applyButton.Name = "_applyButton"; + this._applyButton.Size = new System.Drawing.Size(75, 23); + this._applyButton.TabIndex = 6; + this._applyButton.Text = "Apply"; + this._applyButton.UseVisualStyleBackColor = true; + // + // _serverTypeComboBox + // + this._serverTypeComboBox.FormattingEnabled = true; + this._serverTypeComboBox.Location = new System.Drawing.Point(97, 94); + this._serverTypeComboBox.Name = "_serverTypeComboBox"; + this._serverTypeComboBox.Size = new System.Drawing.Size(121, 21); + this._serverTypeComboBox.TabIndex = 5; + // + // _portTextBox + // + this._portTextBox.Location = new System.Drawing.Point(97, 58); + this._portTextBox.Name = "_portTextBox"; + this._portTextBox.Size = new System.Drawing.Size(121, 20); + this._portTextBox.TabIndex = 4; + // + // _ipAddressComboBox + // + this._ipAddressComboBox.FormattingEnabled = true; + this._ipAddressComboBox.Location = new System.Drawing.Point(97, 21); + this._ipAddressComboBox.Name = "_ipAddressComboBox"; + this._ipAddressComboBox.Size = new System.Drawing.Size(121, 21); + this._ipAddressComboBox.TabIndex = 3; + // + // _serverTypeLabel + // + this._serverTypeLabel.AutoSize = true; + this._serverTypeLabel.Location = new System.Drawing.Point(16, 97); + this._serverTypeLabel.Name = "_serverTypeLabel"; + this._serverTypeLabel.Size = new System.Drawing.Size(68, 13); + this._serverTypeLabel.TabIndex = 2; + this._serverTypeLabel.Text = "Server Type:"; + // + // _portLabel + // + this._portLabel.AutoSize = true; + this._portLabel.Location = new System.Drawing.Point(16, 61); + this._portLabel.Name = "_portLabel"; + this._portLabel.Size = new System.Drawing.Size(29, 13); + this._portLabel.TabIndex = 1; + this._portLabel.Text = "Port:"; + // + // _ipAddressLabel + // + this._ipAddressLabel.AutoSize = true; + this._ipAddressLabel.Location = new System.Drawing.Point(16, 29); + this._ipAddressLabel.Name = "_ipAddressLabel"; + this._ipAddressLabel.Size = new System.Drawing.Size(61, 13); + this._ipAddressLabel.TabIndex = 0; + this._ipAddressLabel.Text = "IP Address:"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1024, 707); + this.Controls.Add(this._serverSettingsGroup); + this.Controls.Add(this._clientsListBox); + this.Controls.Add(this._logsGroupBox); + this.Controls.Add(this._restartButton); + this.Controls.Add(this._stopButton); + this.Controls.Add(this._startButton); + this.Name = "MainForm"; + this.Text = "Server Management Tools"; + this._logsGroupBox.ResumeLayout(false); + this._serverSettingsGroup.ResumeLayout(false); + this._serverSettingsGroup.PerformLayout(); + this._serverParametersBox.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button _startButton; + private System.Windows.Forms.Button _stopButton; + private System.Windows.Forms.Button _restartButton; + private System.Windows.Forms.GroupBox _logsGroupBox; + private System.Windows.Forms.ListBox _clientsListBox; + private System.Windows.Forms.GroupBox _serverSettingsGroup; + private System.Windows.Forms.Label _serverTypeLabel; + private System.Windows.Forms.Label _portLabel; + private System.Windows.Forms.Label _ipAddressLabel; + private System.Windows.Forms.ComboBox _ipAddressComboBox; + private System.Windows.Forms.TextBox _portTextBox; + private System.Windows.Forms.ComboBox _serverTypeComboBox; + private System.Windows.Forms.Button _applyButton; + private System.Windows.Forms.RichTextBox _logsTextBox; + private System.Windows.Forms.GroupBox _serverParametersBox; + private System.Windows.Forms.ListView _serverParametersView; + private System.Windows.Forms.ComboBox _logLevelComboBox; + private System.Windows.Forms.Label _logLevelLabel; + } +} + diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.cs new file mode 100644 index 0000000..658249e --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Windows.Forms; +using log4net; +using log4net.Config; +using log4net.Core; +using log4net.Repository.Hierarchy; +using MossbauerLab.TinyTcpServer.Core.Client; +using MossbauerLab.TinyTcpServer.Core.Server; +using MossbauerLab.TinyTcpServer.MnGUI.Data; +using MossbauerLab.TinyTcpServer.MnGUI.Factories; +using MossbauerLab.TinyTcpServer.MnGUI.LogUtils; +using MossbauerLab.TinyTcpServer.MnGUI.View.Helpers; + +namespace MossbauerLab.TinyTcpServer.MnGUI.View.Forms +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + Load += (sender, args) => FillControls(); + _startButton.Click += (sender, args) => Start(); + _stopButton.Click += (sender, args) => Stop(); + _restartButton.Click += (sender, args) => Restart(); + _logLevelComboBox.SelectedIndexChanged += (sender, args) => ApplyLogLevel(); + } + + private void FillControls() + { + // fill ip address + IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName()); + foreach (IPAddress ip in host.AddressList) + { + if (ip.AddressFamily == AddressFamily.InterNetwork) + _ipAddressComboBox.Items.Add(ip.ToString()); + } + + // load last IP address and TCP Port settings + if (File.Exists(ConfigFile)) + { + String[] filelines = File.ReadAllLines(ConfigFile); + ApplySettings(GetOptions(filelines)); + } + else + { + if (_ipAddressComboBox.Items.Count > 0) + _ipAddressComboBox.SelectedIndex = 0; + _portTextBox.Text = DefaultTcpPort.ToString(); + } + + // add server type + foreach (KeyValuePair server in _servers) + _serverTypeComboBox.Items.Add(server.Value); + _serverTypeComboBox.SelectedIndex = 0; + + // init logger + fill log level + XmlConfigurator.Configure(); + _logger = LogManager.GetLogger(typeof(MainForm)); + _richTextBoxAppender = new RichTextBoxAppender(_logsTextBox); + ((Logger)_logger.Logger).AddAppender(_richTextBoxAppender); + foreach (KeyValuePair level in _logLevels) + _logLevelComboBox.Items.Add(level.Value); + _logLevelComboBox.SelectedIndex = 5; + + // fill server config + IList configStrings = ServerConfigInfoHelper.GetConfigStrings(_serverConfig); + foreach (String configString in configStrings) + _serverParametersView.Items.Add(configString); + } + + private IDictionary GetOptions(String[] lines) + { + IDictionary options = new Dictionary(); + // todo: parse options .... + return options; + } + + private void ApplySettings(IDictionary options) + { + + } + + private void Start() + { + // getting server type + if (_serverTypeComboBox.SelectedIndex < 0) + { + // log + return; + } + ServerType serverType = ServerType.Scripting; + foreach (KeyValuePair server in _servers) + { + if (String.Equals(_serverTypeComboBox.Items[_serverTypeComboBox.SelectedIndex].ToString(), server.Value)) + serverType = server.Key; + } + if (_server == null) + { + _server = ServerFactory.Create(serverType, _ipAddressComboBox.Items[_ipAddressComboBox.SelectedIndex].ToString(), + UInt16.Parse(_portTextBox.Text), _logger, _serverConfig); + } + _server.Start(); + if (_timers[0] == null) + { + System.Threading.Timer periodicalUpdater = new System.Threading.Timer(StateUpdater, null, 500, 500); + _timers[0] = periodicalUpdater; + } + else _timers[0].Change(500, 500); + } + + public void Stop() + { + _server.Stop(false); + if (_timers[0] != null) + { + _timers[0].Change(-1, -1); + } + UpdateControlsState(); + } + + public void Restart() + { + Stop(); + Start(); + } + + void UpdateControlsState() + { + if (_server == null) + return; + _startButton.Enabled = !_server.IsReady; + _restartButton.Enabled = _server.IsReady; + _stopButton.Enabled = _server.IsReady; + _applyButton.Enabled = !_server.IsReady; + _logLevelComboBox.Enabled = !_server.IsReady; + _ipAddressComboBox.Enabled = !_server.IsReady; + _portTextBox.Enabled = !_server.IsReady; + } + + void PopulateClients() + { + _clientsListBox.Items.Clear(); + IList clients = _server.Clients; + if (clients != null) + { + _clientsListBox.Items.Add(String.Format(TotalClientsTemplate, clients.Count)); + foreach (TcpClientContext client in clients) + { + String ipAddress = ((IPEndPoint)client.Client.Client.RemoteEndPoint).Address.ToString(); + _clientsListBox.Items.Add(String.Format(ClientInfoTemplate, client.Id, ipAddress)); + } + } + } + + void StateUpdater(Object state) + { + BeginInvoke((Action)(UpdateControlsState)); + BeginInvoke((Action) PopulateClients); + } + + void ApplyLogLevel() + { + Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(); + hierarchy.Threshold =_logLevels.First(item => item.Value.Equals(_logLevelComboBox.Items[_logLevelComboBox.SelectedIndex].ToString())).Key; + } + + private const String ConfigFile = @".\settings.txt"; + private const UInt16 DefaultTcpPort = 9999; + private const String TotalClientsTemplate = "Total connected clients: {0}"; + private const String ClientInfoTemplate = "Client {0}, ip: {1}"; + + private readonly IDictionary _servers = new Dictionary() + { + {ServerType.Echo, "Echo server"}, + {ServerType.Time, "Time server"}, + }; + + private readonly IDictionary _logLevels = new Dictionary() + { + {Level.Alert, "Alert"}, {Level.Critical, "Critical"}, {Level.Debug, "Debug"}, + {Level.Emergency, "Emergency"}, {Level.Error, "Error"}, {Level.Info, "Info"}, {Level.Warn, "Warn"} + }; + + private ILog _logger; + private RichTextBoxAppender _richTextBoxAppender; + private readonly TcpServerConfig _serverConfig = new TcpServerConfig(); + private ITcpServer _server; + private readonly System.Threading.Timer[] _timers = new System.Threading.Timer[1]; + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.resx b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Forms/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Helpers/ServerConfigInfoHelper.cs b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Helpers/ServerConfigInfoHelper.cs new file mode 100644 index 0000000..3be580a --- /dev/null +++ b/GUI/MossbauerLab.TinyTcpServer.MnGUI/MossbauerLab.TinyTcpServer.MnGUI/View/Helpers/ServerConfigInfoHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using MossbauerLab.TinyTcpServer.Core.Server; + +namespace MossbauerLab.TinyTcpServer.MnGUI.View.Helpers +{ + public static class ServerConfigInfoHelper + { + public static IList GetConfigStrings(TcpServerConfig config) + { + IList strings = new List(); + strings.Add(String.Format(ConnectTimeoutTemplate, config.ClientConnectTimeout)); + strings.Add(String.Format(ReadTimeoutTemplate, config.ReadTimeout)); + strings.Add(String.Format(WriteTimeoutTemplate, config.WriteTimeout)); + strings.Add(String.Format(ServerCloseTimeoutTemplate, config.ServerCloseTimeout)); + strings.Add(String.Format(ClientInactivityTimeTemplate, config.ClientInactivityTime)); + + strings.Add(String.Format(ConnectAttemptsTemplate, config.ClientConnectAttempts)); + strings.Add(String.Format(ReadAttemptsTemplate, config.ClientReadAttempts)); + + strings.Add(String.Format(ParallelTasksTemplate, config.ParallelTask)); + strings.Add(String.Format(ClientBufferSizeTemplate, config.ClientBufferSize)); + return strings; + } + + private const String ConnectTimeoutTemplate = "Connect timeout: {0} ms"; + private const String ReadTimeoutTemplate = "Read timeout: {0} ms"; + private const String WriteTimeoutTemplate = "Write timeout: {0} ms"; + private const String ServerCloseTimeoutTemplate = "Server close timeout: {0} ms"; + private const String ClientInactivityTimeTemplate = "Client inactivity time: {0} s"; + + private const String ConnectAttemptsTemplate = "Connect attempts: {0} times"; + private const String ReadAttemptsTemplate = "Read attempts: {0} times"; + + private const String ParallelTasksTemplate = "Parallel tasks: {0}"; + private const String ClientBufferSizeTemplate = "Client buffer size: {0} bytes"; + } +} diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/MossbauerLab.SimpleExtensions.dll b/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/MossbauerLab.SimpleExtensions.dll new file mode 100644 index 0000000..7bab19a Binary files /dev/null and b/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/MossbauerLab.SimpleExtensions.dll differ diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/MossbauerLab.TinyTcpServer.Core.dll b/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/MossbauerLab.TinyTcpServer.Core.dll new file mode 100644 index 0000000..f8edbe9 Binary files /dev/null and b/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/MossbauerLab.TinyTcpServer.Core.dll differ diff --git a/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/log4net.dll b/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/log4net.dll new file mode 100644 index 0000000..47cd9ad Binary files /dev/null and b/GUI/MossbauerLab.TinyTcpServer.MnGUI/lib/log4net.dll differ diff --git a/TinyTcpServer/MossbauerLab.SimpleExtensions/Echo/EchoTcpServer.cs b/TinyTcpServer/MossbauerLab.SimpleExtensions/Echo/EchoTcpServer.cs index 764a274..bd0f0f5 100644 --- a/TinyTcpServer/MossbauerLab.SimpleExtensions/Echo/EchoTcpServer.cs +++ b/TinyTcpServer/MossbauerLab.SimpleExtensions/Echo/EchoTcpServer.cs @@ -10,8 +10,8 @@ namespace MossbauerLab.SimpleExtensions.Echo /// public class EchoTcpServer : TcpServer { - public EchoTcpServer(String ipAddress, UInt16 port = DefaultEchoPort, ILog logger = null, Boolean debug = false) - : base(ipAddress, port, logger, debug) + public EchoTcpServer(String ipAddress, UInt16 port = DefaultEchoPort, ILog logger = null, Boolean debug = false, TcpServerConfig config = null) + : base(ipAddress, port, logger, debug, config) { AddHandler(new TcpClientHandlerInfo(Guid.NewGuid()), EchoTcpClientHandler.Handle); } diff --git a/TinyTcpServer/MossbauerLab.SimpleExtensions/MossbauerLab.SimpleExtensions.csproj b/TinyTcpServer/MossbauerLab.SimpleExtensions/MossbauerLab.SimpleExtensions.csproj index 87e5047..eb75f6c 100644 --- a/TinyTcpServer/MossbauerLab.SimpleExtensions/MossbauerLab.SimpleExtensions.csproj +++ b/TinyTcpServer/MossbauerLab.SimpleExtensions/MossbauerLab.SimpleExtensions.csproj @@ -9,8 +9,9 @@ Properties MossbauerLab.SimpleExtensions MossbauerLab.SimpleExtensions - v4.5 + v4.0 512 + true diff --git a/TinyTcpServer/MossbauerLab.SimpleExtensions/Time/TimeTcpServer.cs b/TinyTcpServer/MossbauerLab.SimpleExtensions/Time/TimeTcpServer.cs index d735d9d..1e3138b 100644 --- a/TinyTcpServer/MossbauerLab.SimpleExtensions/Time/TimeTcpServer.cs +++ b/TinyTcpServer/MossbauerLab.SimpleExtensions/Time/TimeTcpServer.cs @@ -11,8 +11,8 @@ namespace MossbauerLab.SimpleExtensions.Time /// public class TimeTcpServer : TcpServer { - public TimeTcpServer(String ipAddress, UInt16 port = DefaultTimePort, ILog logger = null, Boolean debug = false) - : base(ipAddress, port, logger, debug) + public TimeTcpServer(String ipAddress, UInt16 port = DefaultTimePort, ILog logger = null, Boolean debug = false, TcpServerConfig config = null) + : base(ipAddress, port, logger, debug, config) { _task = new Task(ClientProccessor); } diff --git a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/MossbauerLab.TinyTcpServer.Core.csproj b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/MossbauerLab.TinyTcpServer.Core.csproj index cf4850e..70afbe4 100644 --- a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/MossbauerLab.TinyTcpServer.Core.csproj +++ b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/MossbauerLab.TinyTcpServer.Core.csproj @@ -50,6 +50,7 @@ + diff --git a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/ITcpServer.cs b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/ITcpServer.cs index 29131f4..ecdb5c0 100644 --- a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/ITcpServer.cs +++ b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/ITcpServer.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using MossbauerLab.TinyTcpServer.Core.Client; using MossbauerLab.TinyTcpServer.Core.Handlers; namespace MossbauerLab.TinyTcpServer.Core.Server @@ -18,6 +20,7 @@ public interface ITcpServer // properties Int32 ConnectedClients { get; } Boolean IsReady { get; } + IList Clients { get; } void DisconnectAllClients(); } } \ No newline at end of file diff --git a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServer.cs b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServer.cs index 39e3c15..8629982 100644 --- a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServer.cs +++ b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServer.cs @@ -17,10 +17,12 @@ namespace MossbauerLab.TinyTcpServer.Core.Server { public class TcpServer : ITcpServer, IDisposable { - public TcpServer(String ipAddress = DefaultServerIpAddress, UInt16 port = DefaultServerPort, ILog logger = null, Boolean debug = false) + public TcpServer(String ipAddress = DefaultServerIpAddress, UInt16 port = DefaultServerPort, ILog logger = null, + Boolean debug = false, TcpServerConfig config = null) { + _config = config ?? new TcpServerConfig(); AssignIpAddressAndPort(ipAddress, port); - _clientProcessingTasks = new Task[_parallelClientProcessingTasks]; + _clientProcessingTasks = new Task[_config.ParallelTask]; _clientConnectingTask = new Task(ClientConnectProcessing, new CancellationToken(_interruptRequested)); if (logger != null) _logger = logger; @@ -56,17 +58,13 @@ public virtual void Stop(Boolean clearHandlers) { _interruptRequested = true; _tcpListener.Stop(); - _tcpListener.Server.Close(ServerCloseTimeout); + _tcpListener.Server.Close(_config.ServerCloseTimeout); if (clearHandlers) ReleaseClientsHandlers(); if (_clientConnectEvent != null) _clientConnectEvent.Dispose(); - /*if (_serverMainTask != null && (_serverMainTask.Status != TaskStatus.Faulted && - _serverMainTask.Status != TaskStatus.RanToCompletion && - _serverMainTask.Status != TaskStatus.Canceled)) - _serverMainTask.Wait(); - if (_serverMainTask != null) - _serverMainTask.Dispose();*/ + _serverStartedProcessing = false; + _logger.Info(ServerStoppedTemplate); } public virtual void Restart() @@ -97,7 +95,7 @@ public Boolean IsReady { if (_tcpListener == null) return false; - return _tcpListener.Server.IsBound && _clientConnectingTask.Status == TaskStatus.Running; + return _tcpListener.Server.IsBound && _serverStartedProcessing; } } @@ -144,10 +142,16 @@ public Int32 ConnectedClients get { return _tcpClients.Count; } } + public IList Clients + { + get { return _tcpClients; } + } + private Boolean StartImpl(Boolean assignNewValues, String ipAddress, UInt16 port) { try { + _serverStartedProcessing = false; _clientConnectEvent = new ManualResetEventSlim(false, 100); _interruptRequested = false; if(assignNewValues) @@ -164,6 +168,7 @@ private Boolean StartImpl(Boolean assignNewValues, String ipAddress, UInt16 port Task.Factory.StartNew(StartClientProcessing); //_serverMainTask = new Task(StartClientProcessing); //_serverMainTask.Start(); + _logger.InfoFormat(ServerStarteTemplated, _ipAddress, _port); return _tcpListener.Server.IsBound; } catch (Exception) @@ -181,7 +186,7 @@ private void AssignIpAddressAndPort(String ipAddress, UInt16 port) if (_tcpListener != null) { ReleaseClients(); - _tcpListener.Server.Close(ServerCloseTimeout); + _tcpListener.Server.Close(_config.ServerCloseTimeout); _tcpListener.Server.Dispose(); _tcpListener.Stop(); } @@ -275,7 +280,7 @@ private void StartClientProcessing() client.Inactive = true; if (client.InactiveTimeMark == default(DateTime)) client.InactiveTimeMark = DateTime.Now; - else if (client.InactiveTimeMark.AddSeconds(DefaultClientInactiveWaitSeconds) < DateTime.Now) + else if (client.InactiveTimeMark.AddSeconds(_config.ClientInactivityTime) < DateTime.Now) { client.ReadDataEvent.Dispose(); client.WriteDataEvent.Dispose(); @@ -290,14 +295,15 @@ private void StartClientProcessing() private void ClientConnectProcessing() { + _serverStartedProcessing = true; Int32 clientsNumber = _tcpClients.Count; - for (Int32 attempt = 0; attempt < _clientConnectAttempts; attempt++) + for (Int32 attempt = 0; attempt < _config.ClientConnectAttempts; attempt++) { if (_interruptRequested) return; _clientConnectEvent.Reset(); _tcpListener.BeginAcceptTcpClient(ConnectAsyncCallback, _tcpListener); - _clientConnectEvent.Wait(_clientConnectTimeout); + _clientConnectEvent.Wait(_config.ClientConnectTimeout); if (_tcpClients.Count > clientsNumber) break; } @@ -319,8 +325,8 @@ private void ConnectAsyncCallback(IAsyncResult state) } catch (Exception) { - //todo: umv: probably we should notify i.e. via logs - _logger.Error("An error occured during client connection"); + if (!_interruptRequested) + _logger.Error("An error occured during client connection"); } _clientConnectEvent.Set(); } @@ -367,24 +373,24 @@ private void ProcessClientReceiveSend(TcpClientContext client) private Byte[] ReceiveImpl(TcpClientContext client) { - Byte[] buffer = new Byte[DefaultClientBufferSize]; + Byte[] buffer = new Byte[_config.ClientBufferSize]; client.BytesRead = 0; try { NetworkStream netStream = client.Client.GetStream(); - netStream.ReadTimeout = DefaultMaximumReadTimeout; - for (Int32 attempt = 0; attempt < _clientReadAttempts; attempt++) + netStream.ReadTimeout = _config.ReadTimeout; + for (Int32 attempt = 0; attempt < _config.ClientReadAttempts; attempt++) { Boolean result = netStream.DataAvailable; while (result) { client.ReadDataEvent.Reset(); - Array.Resize(ref buffer, buffer.Length + DefaultChunkSize); + Array.Resize(ref buffer, buffer.Length + _config.ChunkSize); Int32 offset = client.BytesRead; - Int32 size = DefaultChunkSize; + Int32 size = _config.ChunkSize; netStream.BeginRead(buffer, offset, size, ReadAsyncCallback, client); - client.ReadDataEvent.Wait(_readTimeout); + client.ReadDataEvent.Wait(_config.ReadTimeout); result = netStream.DataAvailable; } } @@ -421,9 +427,9 @@ private void SendImpl(TcpClientContext client, Byte[] data) client.WriteDataEvent.Reset(); NetworkStream netStream = client.Client.GetStream(); - netStream.WriteTimeout = DefaultMaximumWriteTimeout; + netStream.WriteTimeout = _config.WriteTimeout; netStream.BeginWrite(data, 0, data.Length, WriteAsyncCallback, client); - client.WriteDataEvent.Wait(_writeTimeout); + client.WriteDataEvent.Wait(_config.WriteTimeout); } } catch (Exception) @@ -444,36 +450,20 @@ private void WriteAsyncCallback(IAsyncResult state) private const String DefaultServerIpAddress = "127.0.0.1"; private const Int32 DefaultServerPort = 16000; - private const Int32 ServerCloseTimeout = 2000; - private const Int32 DefaultClientBufferSize = 16384; - private const Int32 DefaultChunkSize = 8192; - private const Int32 DefaultClientConnectAttempts = 1; - private const Int32 DefaultMaximumClientConnectTimeout = 50;//200; //ms - private const Int32 DefaultMaximumReadTimeout = 1000; //ms - private const Int32 DefaultMaximumWriteTimeout = 1000; //ms - private const Int32 DefaultReadAttempts = 8; - private const Int32 DefaultParallelClientProcessingTasks = 128; - private const Int32 DefaultClientInactiveWaitSeconds = 120; - private const String ClientRemoveMessagedTemplate = "Client {0} connected from {1} ip was removed due to no activity"; private const String ClientConnectedMessagedTemplate = "Client {0} connected from {1} ip address"; private const String ReceivedDataMessageTemplate = "Received {0} bytes from client {1} {2}"; private const String SendDataMessageTemplate = "There are {0} bytes was sent to client {1} {2}"; + private const String ServerStarteTemplated = "TCP Server successfully started with ip address {0} on {1} port"; + private const String ServerStoppedTemplate = "TCP Server was stopped"; - // timeouts - //todo: umv: make adjustable - private Int32 _clientConnectTimeout = DefaultMaximumClientConnectTimeout; - private Int32 _readTimeout = DefaultMaximumReadTimeout; - private Int32 _writeTimeout = DefaultMaximumWriteTimeout; - // other parameters - private Int32 _clientConnectAttempts = DefaultClientConnectAttempts; - private Int32 _clientReadAttempts = DefaultReadAttempts; - private Int32 _parallelClientProcessingTasks = DefaultParallelClientProcessingTasks; + private readonly TcpServerConfig _config; // threading things private ManualResetEventSlim _clientConnectEvent; private readonly IList _clientProcessingTasks; private Task _clientConnectingTask; + private Boolean _serverStartedProcessing; // private Task _serverMainTask; // server and client entities private String _ipAddress; diff --git a/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServerConfig.cs b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServerConfig.cs new file mode 100644 index 0000000..295a5e8 --- /dev/null +++ b/TinyTcpServer/MossbauerLab.TinyTcpServer.Core/Server/TcpServerConfig.cs @@ -0,0 +1,65 @@ +using System; + +namespace MossbauerLab.TinyTcpServer.Core.Server +{ + public class TcpServerConfig + { + public TcpServerConfig() + { + Init(); + } + + public TcpServerConfig(Int32 clientConnectTimeout = DefaultClientConnectTimeout, Int32 readTimeout = DefaultReadTimeout, + Int32 writeTimeout = DefaultWriteTimeout, Int32 serverCloseTimeout = DefaultServerCloseTimeout, + Int32 clientInactivityTime = DefaultClientInactiveTime, Int32 clientConnectAttempts = DefaultClientConnectAttempts, + Int32 clietnReadAttempts = DefaultReadAttempts, Int32 parallelTasks = DefaultParallelTasks, + Int32 clientBufferSize = DefaultClientBufferSize, Int32 chunkSize = DefaultChunkSize) + { + Init(clientConnectTimeout, readTimeout, writeTimeout, serverCloseTimeout, clientInactivityTime, clientConnectAttempts, + clietnReadAttempts, parallelTasks, clientBufferSize, chunkSize); + } + + private void Init(Int32 clientConnectTimeout = DefaultClientConnectTimeout, Int32 readTimeout = DefaultReadTimeout, + Int32 writeTimeout = DefaultWriteTimeout, Int32 serverCloseTimeout = DefaultServerCloseTimeout, + Int32 clientInactivityTime = DefaultClientInactiveTime, Int32 clientConnectAttempts = DefaultClientConnectAttempts, + Int32 clietnReadAttempts = DefaultReadAttempts, Int32 parallelTasks = DefaultParallelTasks, + Int32 clientBufferSize = DefaultClientBufferSize, Int32 chunkSize = DefaultChunkSize) + { + ClientConnectTimeout = clientConnectTimeout; + ReadTimeout = readTimeout; + WriteTimeout = writeTimeout; + ServerCloseTimeout = serverCloseTimeout; + ClientInactivityTime = clientInactivityTime; + ClientConnectAttempts = clientConnectAttempts; + ClientReadAttempts = clietnReadAttempts; + ParallelTask = parallelTasks; + ClientBufferSize = clientBufferSize; + ChunkSize = chunkSize; + } + + public Int32 ClientConnectTimeout { get; set; } + public Int32 ReadTimeout { get; set; } + public Int32 WriteTimeout { get; set; } + public Int32 ServerCloseTimeout { get; set; } + public Int32 ClientInactivityTime { get; set; } + public Int32 ClientConnectAttempts { get; set; } + public Int32 ClientReadAttempts { get; set; } + + public Int32 ParallelTask { get; set; } + + public Int32 ClientBufferSize { get; set; } + public Int32 ChunkSize { get; set; } + + + private const Int32 DefaultServerCloseTimeout = 2000; + private const Int32 DefaultClientBufferSize = 16384; + private const Int32 DefaultChunkSize = 8192; + private const Int32 DefaultClientConnectAttempts = 1; + private const Int32 DefaultClientConnectTimeout = 50; //ms + private const Int32 DefaultReadTimeout = 1000; //ms + private const Int32 DefaultWriteTimeout = 1000; //ms + private const Int32 DefaultReadAttempts = 8; + private const Int32 DefaultParallelTasks = 128; + private const Int32 DefaultClientInactiveTime = 120; //s (seconds) + } +}