Click here to Skip to main content
15,884,388 members
Articles / Security / Encryption

Creating an FTP Server in C# - with IPv6 Support

Rate me:
Please Sign up or sign in to vote.
4.91/5 (76 votes)
7 Oct 2013MIT20 min read 290.4K   16.4K   173  
An introduction into creating a working FTP server in C# using the RFC specification.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace SharpFtpServer
{
    public class RateLimitingStream : Stream
    {
        private Stream _baseStream;
        private System.Diagnostics.Stopwatch _watch;
        private int _speedLimit;
        private long _transmitted;
        private double _resolution;

        public RateLimitingStream(Stream baseStream, int speedLimit)
            : this(baseStream, speedLimit, 1)
        {
        }

        public RateLimitingStream(Stream baseStream, int speedLimit, double resolution)
        {
            _baseStream = baseStream;
            _watch = new System.Diagnostics.Stopwatch();
            _speedLimit = speedLimit;
            _resolution = resolution;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (!_watch.IsRunning)
            {
                _watch.Start();
            }

            int dataSent = 0;

            while (_speedLimit > 0 && _transmitted >= (_speedLimit * _resolution))
            {
                Thread.Sleep(10);

                if (_watch.ElapsedMilliseconds > (1000 * _resolution))
                {
                    _transmitted = 0;
                    _watch.Restart();
                }
            }

            _baseStream.Write(buffer, offset, count);
            _transmitted += count;
            dataSent += count;

            if (_watch.ElapsedMilliseconds > (1000 * _resolution))
            {
                _transmitted = 0;
                _watch.Restart();
            }
        }

        public override bool CanRead
        {
            get { return false; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            _baseStream.Flush();
        }

        public override long Length
        {
            get { return _baseStream.Length; }
        }

        public override long Position
        {
            get
            {
                return _baseStream.Position;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        protected override void Dispose(bool disposing)
        {
            _watch.Stop();

            base.Dispose(disposing);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
United States United States
I have been a software developer since 2005, focusing on .Net applications with MS SQL backends, and recently, C++ applications in Linux, Mac OS X, and Windows.

Comments and Discussions