C# 搭建FTP通讯 包括客户端服务器端

这里将使用在Winform平台上搭建FTP的通讯。
[项目源码]
链接:https://pan.baidu.com/s/1oPwGmFy9JIwgBNhQa4fcNg
提取码:v2he
复制这段内容后打开百度网盘手机App,操作更方便哦

客户端

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using FTP.Model;
using System.Threading.Tasks;

namespace FTP.Base
{
    public class FtpClient
    {
        private const int BUFFSIZE = 1024 * 2;

        public string ServerIP { get; set; }

        public string UserName { get; set; }

        public string Password { get; set; }

        public string URI { get; set; }

        public Action CompleteDownload = null;

        public Action CompleteUpload = null;

        public Action<string> FailDownload = null;

        public Action<string> FailUpload = null;

        /// <summary>
        /// 设置FTP属性
        /// </summary>
        /// <param name="FtpServerIP">FTP连接地址</param>
        /// <param name="this.UserName">用户名</param>
        /// <param name="Password">密码</param>
        public FtpClient(string serverIP, string userName, string passwordName)
        {
            this.ServerIP = serverIP;
            this.UserName = userName;
            this.Password = passwordName;
            this.URI = "ftp://" + this.ServerIP + "/";
        }

        /// <summary>
        /// 上传
        /// </summary>
        /// <param name="relativePath">服务器的相对路径</param>
        /// <param name="localPath">本地文件的绝对路径</param>
        public void Upload(string relativePath, string localPath)
        {
            try
            {
                Task task = Task.Factory.StartNew(() =>
                {
                    UploadFile(relativePath, localPath);
                });
                task.ContinueWith(t =>
                {
                    if (task.Exception == null)
                    {
                        if (this.CompleteUpload != null)
                            this.CompleteUpload();
                    }
                    else if (this.FailUpload != null)
                    {
                        this.FailUpload(task.Exception.Message);
                    }
                });
            }
            catch (Exception ex)
            {
                if (this.FailUpload != null)
                    this.FailUpload(ex.Message);
            }
            finally
            {

            }
        }

        private void UploadFile(string relativePath, string localPath)
        {
            FtpWebRequest reqFTP = null;
            FileStream fs = null;
            Stream strm = null;
            try
            {
                FileInfo fileInf = new FileInfo(localPath);
                string uri = this.URI + relativePath + "/" + Path.GetFileName(localPath);
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                reqFTP.KeepAlive = false;
                reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
                reqFTP.UseBinary = true;
                reqFTP.UsePassive = false;
                reqFTP.ContentLength = fileInf.Length;
                byte[] buff = new byte[BUFFSIZE];
                int contentLen = 0;
                fs = fileInf.OpenRead();
                strm = reqFTP.GetRequestStream();
                while ((contentLen = fs.Read(buff, 0, buff.Length)) != 0)
                {
                    strm.Write(buff, 0, contentLen);
                }

                if (this.CompleteUpload != null)
                    this.CompleteUpload();
            }
            finally
            {
                if (reqFTP != null)
                    reqFTP.Abort();
                if (fs != null)
                    fs.Close();
                if (strm != null)
                    strm.Close();
            }
        }

        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="filePath">本地保存路径</param>
        /// <param name="fileName">需要下载的FTP服务器路径上的文件名,同时也是本地保存的文件名</param>
        public void Download(string filePath, string serverPath, string fileName)
        {
            try
            {
                Task task = Task.Factory.StartNew(() =>
                    {
                        DownloadFile(filePath, serverPath, fileName);
                    });
                task.ContinueWith(t =>
                {
                    if (task.Exception == null)
                    {
                        if (this.CompleteDownload != null)
                            this.CompleteDownload();
                    }
                    else if (this.FailDownload != null)
                    {
                        List<string> ex = new List<string>();
                        foreach (var item in t.Exception.InnerExceptions)
                        {
                            ex.Add(item.Message);
                        }
                        this.FailDownload(string.Join("\n", ex));
                    }
                });
            }
            catch (Exception ex)
            {
                if (this.FailDownload != null)
                    this.FailDownload(ex.Message);
            }
            finally
            {

            }
        }

        private void DownloadFile(string filePath, string serverPath, string fileName)
        {
            FtpWebRequest ftpRequest = null;
            FileStream outputStream = null;
            FtpWebResponse response = null;
            Stream ftpStream = null;

            try
            {
                outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);
                string uri = this.URI + serverPath + "/" + fileName;
                ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
                ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                ftpRequest.UseBinary = true;
                ftpRequest.UsePassive = false;
                ftpRequest.Proxy = null;
                ftpRequest.Credentials = new NetworkCredential(this.UserName, this.Password);
                response = (FtpWebResponse)ftpRequest.GetResponse();
                ftpStream = response.GetResponseStream();
                //long needRead = response.ContentLength, realRead = 0; // 出现response.ContentLength=-1但仍能下载的情况,原因?
                int readCount = 0;
                byte[] buffer = new byte[BUFFSIZE];

                while ((readCount = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    //realRead += readCount;
                }
            }
            finally
            {
                if (ftpRequest != null)
                    ftpRequest.Abort();
                if (ftpStream != null)
                    ftpStream.Close();
                if (response != null)
                    response.Close();
                if (outputStream != null)
                    outputStream.Close();
            }
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fileName"></param>
        public void Delete(string fileName)
        {
            try
            {
                string uri = this.URI + fileName;
                FtpWebRequest reqFTP;
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));

                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                reqFTP.KeepAlive = false;
                reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;
                reqFTP.UsePassive = false;

                string result = String.Empty;
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                long size = response.ContentLength;
                Stream datastream = response.GetResponseStream();
                StreamReader sr = new StreamReader(datastream);
                result = sr.ReadToEnd();
                sr.Close();
                datastream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                throw new Exception("FtpHelper Delete Error --> " + ex.Message + "  文件名:" + fileName);
            }
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="folderName"></param>
        public void RemoveDirectory(string folderName)
        {
            try
            {
                string uri = this.URI + folderName;
                FtpWebRequest reqFTP;
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));

                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                reqFTP.KeepAlive = false;
                reqFTP.Method = WebRequestMethods.Ftp.RemoveDirectory;
                reqFTP.UsePassive = false;

                string result = String.Empty;
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                long size = response.ContentLength;
                Stream datastream = response.GetResponseStream();
                StreamReader sr = new StreamReader(datastream);
                result = sr.ReadToEnd();
                sr.Close();
                datastream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                throw new Exception("FtpHelper Delete Error --> " + ex.Message + "  文件名:" + folderName);
            }
        }

        /// <summary>
        /// 获取当前目录下明细(包含文件和文件夹),并按文件种类排序(文件在前,文件夹在后)
        /// </summary>
        /// <param name="path">相对FTP根目录的路径</param>
        /// <returns></returns>
        public List<FtpFileModel> GetFilesDetailList(string path = "")
        {
            Console.WriteLine(path);
            FtpWebRequest ftp = null;
            WebResponse response = null;
            StreamReader reader = null;
            List<FtpFileModel> fileList = new List<FtpFileModel>();
            try
            {
                StringBuilder result = new StringBuilder();
                ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.URI + path));
                ftp.Credentials = new NetworkCredential(this.UserName, Password);
                ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                ftp.UsePassive = false;
                response = ftp.GetResponse();
                reader = new StreamReader(response.GetResponseStream(), Encoding.Default);

                string line = string.Empty;// 读取的首行内容为"total 0",剔除
                while ((line = reader.ReadLine()) != null)
                {
                    try
                    {
                        fileList.Add(new FtpFileModel(line, path));
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            catch (Exception ex)
            {
                
            }
            finally
            {
                if (reader != null)
                    reader.Close();
                if (response != null)
                    response.Close();
                if (ftp != null)
                    ftp.Abort();
            }

            return fileList.OrderBy(f => f.FileType).ToList();
        }

        /// <summary>
        /// 获取当前目录下文件列表(仅文件)
        /// </summary>
        /// <returns></returns>
        public string[] GetFileList(string mask)
        {
            string[] downloadFiles;
            StringBuilder result = new StringBuilder();
            FtpWebRequest reqFTP;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.URI));
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
                reqFTP.UsePassive = false;
                WebResponse response = reqFTP.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);

                string line = reader.ReadLine();
                while (line != null)
                {
                    if (mask.Trim() != string.Empty && mask.Trim() != "*.*")
                    {
                        string mask_ = mask.Substring(0, mask.IndexOf("*"));
                        if (line.Substring(0, mask_.Length) == mask_)
                        {
                            result.Append(line);
                            result.Append("\n");
                        }
                    }
                    else
                    {
                        result.Append(line);
                        result.Append("\n");
                    }
                    line = reader.ReadLine();
                }
                result.Remove(result.ToString().LastIndexOf('\n'), 1);
                reader.Close();
                response.Close();
                return result.ToString().Split('\n');
            }
            catch (Exception ex)
            {
                downloadFiles = null;
                if (ex.Message.Trim() != "远程服务器返回错误: (550) 文件不可用(例如,未找到文件,无法访问文件)。")
                {
                    throw new Exception("FtpHelper GetFileList Error --> " + ex.Message.ToString());
                }
                return downloadFiles;
            }
        }
        
        /// <summary>
        /// 判断当前目录下指定的文件是否存在
        /// </summary>
        /// <param name="RemoteFileName">远程文件名</param>
        public bool FileExist(string RemoteFileName)
        {
            string[] fileList = GetFileList("*.*");
            foreach (string str in fileList)
            {
                if (str.Trim() == RemoteFileName.Trim())
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <param name="dirName"></param>
        public void MakeDir(string dirName)
        {
            FtpWebRequest reqFTP;
            try
            {
                // dirName = name of the directory to create.
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.URI + dirName));
                reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
                reqFTP.UseBinary = true;
                reqFTP.UsePassive = false;
                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                throw new Exception("FtpHelper MakeDir Error --> " + ex.Message);
            }
        }

        /// <summary>
        /// 获取指定文件大小
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public long GetFileSize(string filename)
        {
            FtpWebRequest reqFTP;
            long fileSize = 0;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.URI + filename));
                reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
                reqFTP.UseBinary = true;
                reqFTP.UsePassive = false;
                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                fileSize = response.ContentLength;

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                throw new Exception("FtpHelper GetFileSize Error --> " + ex.Message);
            }
            return fileSize;
        }

        /// <summary>
        /// 改名
        /// </summary>
        /// <param name="currentFilename"></param>
        /// <param name="newFilename"></param>
        public void ReName(string currentFilename, string newFilename)
        {
            FtpWebRequest reqFTP;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.URI + currentFilename));
                reqFTP.Method = WebRequestMethods.Ftp.Rename;
                reqFTP.RenameTo = newFilename;
                reqFTP.UseBinary = true;
                reqFTP.UsePassive = false;
                reqFTP.Credentials = new NetworkCredential(this.UserName, Password);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                throw new Exception("FtpHelper ReName Error --> " + ex.Message);
            }
        }

        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="currentFilename"></param>
        /// <param name="newFilename"></param>
        public void MovieFile(string currentFilename, string newDirectory)
        {
            ReName(currentFilename, newDirectory);
        }
    }
}

服务器

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace FTP.Base
{
    public class FtpServer : IDisposable
    {
        private bool _disposed = false;
        private bool _listening = false;
        private TcpListener _listener = null;
        private List<ClientConnection> _activeConnections = null;
        private Dictionary<string, string> _accounts = new Dictionary<string, string>();

        public byte[] IP { get; set; }
        public int Port { get; set; }
        public string RootDirectory { get; set; }

        public FtpServer(string ip, int port, string root)
        {
            string[] ips = ip.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            this.IP = new byte[4];
            for (int i = 0; i < 4; ++i)
            {
                this.IP[i] = Convert.ToByte(ips[i]);
            }
            this.Port = port;
            this.RootDirectory = root;

            this._accounts["ftptest"] = "123456";
        }

        public void Start()
        {
            _listener = new TcpListener(new IPAddress(this.IP), this.Port);
            _listener.Start();
            _activeConnections = new List<ClientConnection>();
            _listening = true;
            _listener.BeginAcceptTcpClient(HandleAcceptTcpClient, _listener);
        }

        public void Stop()
        {
            _listening = false;
            _listener.Stop();
            _listener = null;
        }

        public void AddUser(string userName, string pwd)
        {
            this._accounts[userName] = pwd;
        }

        private void HandleAcceptTcpClient(IAsyncResult result)
        {
            if (_listening)
            {
                _listener.BeginAcceptTcpClient(HandleAcceptTcpClient, _listener);
                TcpClient client = _listener.EndAcceptTcpClient(result);
                ClientConnection connection = new ClientConnection(client, this.RootDirectory);
                connection.CheckUser = CheckUser;
                _activeConnections.Add(connection);
                ThreadPool.QueueUserWorkItem(connection.HandleClient, client);
            }
        }

        private bool CheckUser(string userName, string pwd)
        {
            return this._accounts.ContainsKey(userName) && this._accounts[userName] == pwd;
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    if (_listener != null)
                    {
                        _listening = false;
                        _listener.Stop();
                    }

                    foreach (ClientConnection conn in _activeConnections)
                    {
                    }
                }
            }

            _disposed = true;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace FTP.Base
{
    internal class ClientConnection
    {
        private enum DataConnectionType
        {
            Active,
            Passive
        }

        private TcpClient _controlClient = null;
        private TcpClient _dataClient;

        private NetworkStream _controlStream = null;
        private StreamReader _controlReader = null;
        private StreamWriter _controlWriter = null;

        private NetworkStream _dataStream = null;

        private string _username = null;
        private string _transferType = null;

        private DataConnectionType _dataConnectionType;
        private IPEndPoint _dataEndpoint = null;
        private TcpListener _passiveListener = null;
        private StreamReader _dataReader = null;
        private StreamWriter _dataWriter = null;
        private X509Certificate _cert = null;
        private SslStream _sslStream = null;

        private bool _isLogin = false;
        private string _rootDirectory = string.Empty;
        private string _currentDirectory = string.Empty;

        public Func<string, string, bool> CheckUser = null;

        public ClientConnection(TcpClient client, string root)
        {
            _controlClient = client;
            _controlStream = _controlClient.GetStream();
            _controlReader = new StreamReader(_controlStream);
            _controlWriter = new StreamWriter(_controlStream);
            this._rootDirectory = root;
            this._currentDirectory = root;
        }

        public void HandleClient(object obj)
        {
            _controlWriter.WriteLine("220 Service Ready.");
            _controlWriter.Flush();

            string line;

            try
            {
                while (!string.IsNullOrEmpty(line = _controlReader.ReadLine()))
                {
                    Console.WriteLine(line);
                    string response = null;

                    string[] command = line.Split(' ');

                    string cmd = command[0].ToUpperInvariant();
                    string arguments = command.Length > 1 ? line.Substring(command[0].Length + 1) : null;

                    if (string.IsNullOrWhiteSpace(arguments))
                        arguments = null;

                    if (cmd != "USER" && cmd != "PASS" && _isLogin == false)
                        return;

                    if (response == null)
                    {
                        switch (cmd)
                        {
                            case "USER":
                                response = User(arguments);
                                break;
                            case "PASS":
                                response = Password(arguments);
                                break;
                            case "CWD":
                                response = ChangeWorkingDirectory(arguments);
                                break;
                            case "CDUP":
                                response = ChangeWorkingDirectory("..");
                                break;
                            case "PORT":
                                response = Port(arguments);
                                break;
                            case "PASV":
                                response = Passive();
                                break;
                            case "LIST":
                                response = List(arguments);
                                break;
                            case "PWD":
                                response = "257 \"/\" is current directory.";
                                break;
                            case "RETR":
                                response = Retrieve(arguments);
                                break;
                            case "AUTH":
                                response = Auth(arguments);
                                break;
                            case "QUIT":
                                response = "221 Service closing control connection";
                                break;
                            case "TYPE":
                                string[] splitArgs = arguments.Split(' ');
                                response = Type(splitArgs[0], splitArgs.Length > 1 ? splitArgs[1] : null);
                                break;
                            default:
                                response = "502 Command not implemented";
                                break;
                        }
                    }

                    if (_controlClient == null || !_controlClient.Connected)
                    {
                        break;
                    }
                    else
                    {
                        _controlWriter.WriteLine(response);
                        _controlWriter.Flush();

                        // Close the connection
                        if (response.StartsWith("221"))
                        {
                            break;
                        }

                        if (cmd == "AUTH")
                        {
                            _cert = new X509Certificate("server.cer");

                            _sslStream = new SslStream(_controlStream);

                            _sslStream.AuthenticateAsServer(_cert);

                            _controlReader = new StreamReader(_sslStream);
                            _controlWriter = new StreamWriter(_sslStream);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        #region File System Methods

        private static long CopyStream(Stream input, Stream output, int bufferSize)
        {
            byte[] buffer = new byte[bufferSize];
            int count = 0;
            long total = 0;

            while ((count = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, count);
                total += count;
            }

            return total;
        }

        private static long CopyStreamAscii(Stream input, Stream output, int bufferSize)
        {
            char[] buffer = new char[bufferSize];
            int count = 0;
            long total = 0;

            using (StreamReader rdr = new StreamReader(input))
            {
                using (StreamWriter wtr = new StreamWriter(output, Encoding.UTF8))
                {
                    while ((count = rdr.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        wtr.Write(buffer, 0, count);
                        total += count;
                    }
                }
            }

            return total;
        }

        private long CopyStream(Stream input, Stream output)
        {
            if (_transferType == "I")
            {
                return CopyStream(input, output, 4096);
            }
            else
            {
                return CopyStreamAscii(input, output, 4096);
            }
        }

        private bool IsPathValid(string pathname)
        {
            return true;
        }

        private string NormalizeFilename(string pathname)
        {
            return Path.Combine(_currentDirectory, pathname);
        }

        #endregion

        #region FTP Commands

        private string User(string username)
        {
            _username = username;

            return "331 Username ok, need password";
        }

        private string Password(string password)
        {
            if (this.CheckUser != null && this.CheckUser(this._username, password))
            {
                this._isLogin = true;
                return "230 User logged in";
            }
            else
            {
                this._isLogin = false;
                return "530 Not logged in";
            }
        }

        private string Retrieve(string pathname)
        {
            pathname = NormalizeFilename(pathname);

            if (IsPathValid(pathname))
            {
                if (File.Exists(pathname))
                {
                    if (_dataConnectionType == DataConnectionType.Active)
                    {
                        _dataClient = new TcpClient();
                        _dataClient.BeginConnect(_dataEndpoint.Address, _dataEndpoint.Port, DoRetrieve, pathname);
                    }
                    else
                    {
                        _passiveListener.BeginAcceptTcpClient(DoRetrieve, pathname);
                    }

                    return string.Format("150 Opening {0} mode data transfer for RETR", _dataConnectionType);
                }
            }

            return "550 File Not Found";
        }

        private string Auth(string authMode)
        {
            if (authMode == "TLS")
            {
                return "234 Enabling TLS Connection";
            }
            else
            {
                return "504 Unrecognized AUTH mode";
            }
        }

        private string ChangeWorkingDirectory(string pathname)
        {
            pathname = pathname.TrimStart('/');
            pathname = pathname.Replace('/', '\\');
            this._currentDirectory = this._rootDirectory + "\\" + pathname;
            return "200 Changed to new directory";
        }

        private string Type(string typeCode, string formatControl)
        {
            string response = "500 ERROR";

            switch (typeCode)
            {
                case "A":
                case "I":
                    _transferType = typeCode;
                    response = "200 OK";
                    break;
                case "E":
                case "L":
                default:
                    response = "504 Command not implemented for that parameter.";
                    break;
            }

            if (formatControl != null)
            {
                switch (formatControl)
                {
                    case "N":
                        response = "200 OK";
                        break;
                    case "T":
                    case "C":
                    default:
                        response = "504 Command not implemented for that parameter.";
                        break;
                }
            }

            return response;
        }

        private string Port(string hostPort)
        {
            _dataConnectionType = DataConnectionType.Active;

            string[] ipAndPort = hostPort.Split(',');

            byte[] ipAddress = new byte[4];
            byte[] port = new byte[4];

            for (int i = 0; i < 4; i++)
            {
                ipAddress[i] = Convert.ToByte(ipAndPort[i]);
            }

            for (int i = 4; i < 6; i++)
            {
                port[i - 4 + 2] = Convert.ToByte(ipAndPort[i]);
            }

            if (BitConverter.IsLittleEndian)
                Array.Reverse(port);

            var v1 = new IPAddress(ipAddress);
            var v2 = BitConverter.ToInt16(port, 0);
            _dataEndpoint = new IPEndPoint(new IPAddress(ipAddress), BitConverter.ToInt32(port, 0));

            return "200 Data Connection Established";
        }

        private string Passive()
        {
            _dataConnectionType = DataConnectionType.Passive;

            IPAddress localAddress = ((IPEndPoint)_controlClient.Client.LocalEndPoint).Address;

            _passiveListener = new TcpListener(localAddress, 0);
            _passiveListener.Start();

            IPEndPoint localEndpoint = ((IPEndPoint)_passiveListener.LocalEndpoint);

            byte[] address = localEndpoint.Address.GetAddressBytes();
            short port = (short)localEndpoint.Port;

            byte[] portArray = BitConverter.GetBytes(port);

            if (BitConverter.IsLittleEndian)
                Array.Reverse(portArray);

            return string.Format("227 Entering Passive Mode ({0},{1},{2},{3},{4},{5})", address[0], address[1], address[2], address[3], portArray[0], portArray[1]);
        }

        private string List(string pathname)
        {
            if (pathname == null)
            {
                pathname = string.Empty;
            }

            pathname = new DirectoryInfo(Path.Combine(_currentDirectory, pathname)).FullName;

            if (IsPathValid(pathname))
            {
                if (_dataConnectionType == DataConnectionType.Active)
                {
                    _dataClient = new TcpClient();
                    _dataClient.BeginConnect(_dataEndpoint.Address, _dataEndpoint.Port, DoList, pathname);
                }
                else
                {
                    _passiveListener.BeginAcceptTcpClient(DoList, pathname);
                }

                return string.Format("150 Opening {0} mode data transfer for LIST", _dataConnectionType);
            }

            return "450 Requested file action not taken";
        }

        #endregion

        #region Async Methods
        private void DoRetrieve(IAsyncResult result)
        {
            if (_dataConnectionType == DataConnectionType.Active)
            {
                _dataClient.EndConnect(result);
            }
            else
            {
                _dataClient = _passiveListener.EndAcceptTcpClient(result);
            }

            string pathname = (string)result.AsyncState;

            using (NetworkStream dataStream = _dataClient.GetStream())
            {
                using (FileStream fs = new FileStream(pathname, FileMode.Open, FileAccess.Read))
                {
                    CopyStream(fs, dataStream);
                }
            }

            _dataClient.Close();
            _dataClient = null;
            _controlWriter.WriteLine("226 Closing data connection, file transfer successful");
            _controlWriter.Flush();
        }

        private void DoList(IAsyncResult result)
        {
            if (_dataConnectionType == DataConnectionType.Active)
            {
                _dataClient.EndConnect(result);
            }
            else
            {
                _dataClient = _passiveListener.EndAcceptTcpClient(result);
            }

            string pathname = (string)result.AsyncState;

            using (NetworkStream dataStream = _dataClient.GetStream())
            {
                _dataReader = new StreamReader(dataStream, Encoding.UTF8);
                _dataWriter = new StreamWriter(dataStream, Encoding.UTF8);

                IEnumerable<string> directories = Directory.EnumerateDirectories(pathname);

                foreach (string dir in directories)
                {
                    DirectoryInfo d = new DirectoryInfo(dir);

                    string date = d.LastWriteTime < DateTime.Now - TimeSpan.FromDays(180) ?
                        d.LastWriteTime.ToString("MMM dd  yyyy") :
                        d.LastWriteTime.ToString("MMM dd HH:mm");

                    string line = string.Format("drwxr-xr-x    2 2003     2003     {0,8} {1} {2}", "4096", date, d.Name);

                    _dataWriter.WriteLine(line);
                    _dataWriter.Flush();
                }

                IEnumerable<string> files = Directory.EnumerateFiles(pathname);

                foreach (string file in files)
                {
                    FileInfo f = new FileInfo(file);

                    string date = f.LastWriteTime < DateTime.Now - TimeSpan.FromDays(180) ?
                        f.LastWriteTime.ToString("MMM dd  yyyy") :
                        f.LastWriteTime.ToString("MMM dd HH:mm");

                    string line = string.Format("-rw-r--r--    2 2003     2003     {0,8} {1} {2}", f.Length, date, f.Name);

                    _dataWriter.WriteLine(line);
                    _dataWriter.Flush();
                }
            }

            _dataClient.Close();
            _dataClient = null;

            _controlWriter.WriteLine("226 Transfer complete");
            _controlWriter.Flush();
        }

        #endregion
    }
}
  • 7
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值