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)
+ }
+}