/// <summary>
        /// Internal method which reacts on incoming bytes on the currently active socket connection.
        /// Only one of this connection is active at one time.
        /// </summary>
        protected async Task RunReceiveLoopAsync(IDisposable parentDisposable, Socket socket, IPEndPoint localEndPoint, IPEndPoint partnerEndPoint, CancellationToken cancelToken)
        {
            parentDisposable.MustNotBeNull(nameof(parentDisposable));
            socket.MustNotBeNull(nameof(socket));
            localEndPoint.MustNotBeNull(nameof(localEndPoint));
            partnerEndPoint.MustNotBeNull(nameof(partnerEndPoint));

            _lastSuccessfulConnectTimestampUtc = DateTime.UtcNow;

            var localEndPointStr   = localEndPoint.ToString();
            var partnerEndPointStr = partnerEndPoint.ToString();
            var newConnection      = true;

            if (this.IsLoggerSet)
            {
                this.Log(
                    LoggingMessageType.Info,
                    StringBuffer.Format("Starting receive loop for connection {0} to {1}", localEndPointStr, partnerEndPointStr));
            }

            var receiveBuffer = new byte[this.ReceiveBufferSize];

            while (!cancelToken.IsCancellationRequested)
            {
                int lastReceiveResult;
                try
                {
                    // Read next bytes
#if NETSTANDARD2_0
                    var receiveTask = socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), SocketFlags.None);
                    if (receiveTask.IsCompleted)
                    {
                        lastReceiveResult = receiveTask.Result;
                    }
                    else if (this.ReceiveTimeout == TimeSpan.Zero)
                    {
                        lastReceiveResult = await receiveTask
                                            .ConfigureAwait(false);
                    }
                    else
                    {
                        var timeoutTask = Task.Delay(this.ReceiveTimeout);
                        await Task.WhenAny(receiveTask, timeoutTask)
                        .ConfigureAwait(false);

                        if (receiveTask.IsCompleted)
                        {
                            lastReceiveResult = receiveTask.Result;
                        }
                        else
                        {
                            _ = receiveTask.ContinueWith(s_dummyReceiveContinuation);

                            if (this.IsLoggerSet)
                            {
                                this.Log(
                                    LoggingMessageType.Error,
                                    StringBuffer.Format(
                                        "Timeout while receiving from {0}!",
                                        partnerEndPointStr));
                            }
                            break;
                        }
                    }
#else
                    var receiveTaskStruct = socket.ReceiveAsync(new Memory <byte>(receiveBuffer), SocketFlags.None);
                    if (receiveTaskStruct.IsCompleted)
                    {
                        lastReceiveResult = receiveTaskStruct.Result;
                    }
                    else if (this.ReceiveTimeout == TimeSpan.Zero)
                    {
                        lastReceiveResult = await receiveTaskStruct
                                            .ConfigureAwait(false);
                    }
                    else
                    {
                        var receiveTask = receiveTaskStruct.AsTask();
                        var timeoutTask = Task.Delay(this.ReceiveTimeout);
                        await Task.WhenAny(receiveTask, timeoutTask)
                        .ConfigureAwait(false);

                        if (receiveTask.IsCompleted)
                        {
                            lastReceiveResult = receiveTask.Result;
                        }
                        else
                        {
                            _ = receiveTask.ContinueWith(s_dummyReceiveContinuation);

                            if (this.IsLoggerSet)
                            {
                                this.Log(
                                    LoggingMessageType.Error,
                                    StringBuffer.Format(
                                        "Timeout while receiving from {0}!",
                                        partnerEndPointStr));
                            }
                            break;
                        }
                    }
#endif

                    // Reset receive result if we where canceled already
                    if (lastReceiveResult == 0)
                    {
                        this.Log(LoggingMessageType.Info, "Connection closed by remote partner");
                    }
                    else if (cancelToken.IsCancellationRequested)
                    {
                        this.Log(LoggingMessageType.Info, "Connection canceled by local program");
                        lastReceiveResult = 0;
                    }
                    else
                    {
                        _lastSuccessfulReceiveTimestampUtc = DateTime.UtcNow;
                    }
                }
                catch (ObjectDisposedException)
                {
                    break;
                }
                catch (SocketException socketException)
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format(
                                "Error while receiving bytes from {0}: (Code: {1}) {2}",
                                partnerEndPointStr,
                                socketException.SocketErrorCode.ToString(),
                                socketException.Message),
                            exception: socketException);
                    }
                    break;
                }
                catch (Exception ex)
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format(
                                "Error while receiving bytes from {0}: {1}",
                                partnerEndPointStr,
                                ex.Message),
                            exception: ex);
                    }
                    break;
                }

                if (lastReceiveResult <= 0)
                {
                    break;
                }
                this.ProcessReceivedBytes(newConnection, receiveBuffer, lastReceiveResult);

                newConnection = false;
            }

            // Ensure that the socket is closed after ending this method
            TcpAsyncUtil.SafeDispose(parentDisposable);
        }