public async System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken CancellationToken = default)
        {
            if (this.WebSocket == null)
            {
                this.WebSocket = new System.Net.WebSockets.ClientWebSocket();
                foreach (System.Collections.Generic.KeyValuePair <System.String, System.String> Header in this.Headers)
                {
                    WebSocket.Options.SetRequestHeader(Header.Key, Header.Value);
                }

                if (this.PingInterval != System.TimeSpan.Zero)
                {
                    WebSocket.Options.SetRequestHeader("pingInterval", this.PingInterval.TotalMilliseconds.ToString());
                }
            }

            switch (this.WebSocket.State)
            {
            case System.Net.WebSockets.WebSocketState.Connecting:
            case System.Net.WebSockets.WebSocketState.Open:
                return;

            default:
                break;
            }

            if (!(this._IsReconnection))
            {
                this.State = SoftmakeAll.SDK.Communication.ClientWebSocket.ConnectionStates.Connecting;
            }
            else
            {
                this.Reconnecting?.Invoke(null);
                this.State = SoftmakeAll.SDK.Communication.ClientWebSocket.ConnectionStates.Reconnecting;
            }

            try
            {
                await this.WebSocket.ConnectAsync(new System.Uri(this.URL), CancellationToken);
            }
            catch
            {
                this.State = SoftmakeAll.SDK.Communication.ClientWebSocket.ConnectionStates.Disconnected;
                throw;
            }

            if (this.WebSocket.State != System.Net.WebSockets.WebSocketState.Open)
            {
                this.State = SoftmakeAll.SDK.Communication.ClientWebSocket.ConnectionStates.Disconnected;
                return;
            }

            this.State = SoftmakeAll.SDK.Communication.ClientWebSocket.ConnectionStates.Connected;
            if (this._IsReconnection)
            {
                this.Reconnected?.Invoke(null);
            }

            _ = System.Threading.Tasks.Task.Run(async() =>
            {
                const System.Int16 BufferSize = 512;
                System.Net.WebSockets.WebSocketReceiveResult Result;
                do
                {
                    System.Collections.Generic.IEnumerable <System.Byte> Data = new System.Byte[] { };
                    do
                    {
                        System.Byte[] Buffer = new System.Byte[BufferSize];
                        Result = await this.WebSocket.ReceiveAsync(new System.ArraySegment <System.Byte>(Buffer), System.Threading.CancellationToken.None);
                        if (Result.MessageType == System.Net.WebSockets.WebSocketMessageType.Text)
                        {
                            Data = Data.Concat(Buffer);
                        }
                    }while (!(Result.EndOfMessage));

                    if ((Result.MessageType == System.Net.WebSockets.WebSocketMessageType.Text) && (this.ReceiveMessageAction != null))
                    {
                        System.String Message = System.Text.Encoding.UTF8.GetString(Data.SkipLast(BufferSize - Result.Count).ToArray());

                        if (!(Message.StartsWith("{\"pong\":")))
                        {
                            this.ReceiveMessageAction?.Invoke(Message);
                        }
                        else
                        {
                            System.Int64 ServerUnixTime = Message.ToJsonElement().GetInt64("pong");
                            this._Latency = ServerUnixTime > 0 ? System.DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - ServerUnixTime : 0;

                            /*
                             #if DEBUG
                             * System.Console.WriteLine(Message); // Debug Pong Messages
                             #endif
                             */
                        }
                    }
                    else if (Result.MessageType == System.Net.WebSockets.WebSocketMessageType.Close)
                    {
                        this.State = SoftmakeAll.SDK.Communication.ClientWebSocket.ConnectionStates.Disconnected;
                        this.Closed?.Invoke(Result.CloseStatus == System.Net.WebSockets.WebSocketCloseStatus.NormalClosure || Result.CloseStatusDescription == null ? null : new System.Exception(Result.CloseStatusDescription));
                    }
                }while (this.WebSocket.State == System.Net.WebSockets.WebSocketState.Open);
            });

            if ((!(this._IsReconnection)) && (this.PingInterval != System.TimeSpan.Zero))
            {
                this._ReconnectionTimer = new System.Threading.Timer(this.Reconnect, null, System.TimeSpan.Zero, this.PingInterval);
            }

            this._IsReconnection = true;
        }
        private async System.Threading.Tasks.Task ProcessRequestAsync(System.Net.HttpListenerContext HttpListenerContext, System.Threading.CancellationToken CancellationToken = default)
        {
            System.Net.WebSockets.WebSocketContext WebSocketContext = null;
            try
            {
                WebSocketContext = await HttpListenerContext.AcceptWebSocketAsync(null);
            }
            catch
            {
                HttpListenerContext.Response.StatusCode = 500;
                HttpListenerContext.Response.Close();
                return;
            }

            SoftmakeAll.SDK.Communication.ServerWebSocket.ConnectionProperties ConnectionProperties = new SoftmakeAll.SDK.Communication.ServerWebSocket.ConnectionProperties(WebSocketContext);

            lock (this.SyncRoot)
                this.ActiveConnections.Add(ConnectionProperties.ConnectionID, ConnectionProperties);

            this.ClientConnected?.Invoke(ConnectionProperties.ConnectionID);

            const System.Int16 BufferSize = 512;

            System.Net.WebSockets.WebSocketReceiveResult Result;
            do
            {
                System.Collections.Generic.IEnumerable <System.Byte> Data = new System.Byte[] { };
                do
                {
                    System.Byte[] Buffer = new System.Byte[BufferSize];
                    Result = await WebSocketContext.WebSocket.ReceiveAsync(new System.ArraySegment <System.Byte>(Buffer), CancellationToken);

                    if (Result.MessageType == System.Net.WebSockets.WebSocketMessageType.Text)
                    {
                        Data = Data.Concat(Buffer);
                    }
                }while (!(Result.EndOfMessage));

                if ((Result.MessageType == System.Net.WebSockets.WebSocketMessageType.Text) && (this.ReceiveMessageFunc != null))
                {
                    await this.ReplyAsync(ConnectionProperties, System.Text.Encoding.UTF8.GetString(Data.SkipLast(BufferSize - Result.Count).ToArray()), CancellationToken);
                }
                else if (Result.MessageType == System.Net.WebSockets.WebSocketMessageType.Close)
                {
                    await this.DropConnectionAsync(ConnectionProperties, true, CancellationToken);
                }
            }while (WebSocketContext.WebSocket.State == System.Net.WebSockets.WebSocketState.Open);
        }