c# Ftp协议Socket实现

原来用WebRequest来传输文件,被人鄙视了。就弄个Socket版的,支持ActivePassive模式。

带事件日志,有时间的人可以拿去做C#版的flashfxp

Using System;

Using System.Net;

Using System.Net.Socket;

 

Public class FtpClient

    {

        public class FtpLogEventArgs : EventArgs

        {

            private string mStrLog = string.Empty;

            public string Log

            {

                get

                {

                    return this.mStrLog;

                }

            }

            public FtpLogEventArgs(string strLog)

            {

                this.mStrLog = strLog;

            }

        }

        public delegate void FtpLogEventHandler(object sender, FtpLogEventArgs e);

        public class FtpTranProgressEventArgs : EventArgs

        {

            private uint mPercent = 0u;

            private bool mCancel = false;

            public uint Percent

            {

                get

                {

                    return this.mPercent;

                }

            }

            public bool Cancel

            {

                get

                {

                    return this.mCancel;

                }

                set

                {

                }

            }

            public FtpTranProgressEventArgs(uint percent)

            {

                this.mPercent = percent;

                this.mCancel = false;

            }

        }

        public delegate void FtpTranProgressEventHandler(object sender, FtpTranProgressEventArgs e);

        public enum FtpTransferType

        {

            Binary,

            ASCII

        }

        public enum FtpMode

        {

            Active,

            Passive

        }

        public enum FtpSystemType

        {

            UNIX,

            WINDOWS

        }

        private Socket mSocketConnect = null;

        private string mStrServer = string.Empty;

        private int mIntPort = 21;

        private string mStrUser = string.Empty;

        private string mStrPassword = string.Empty;

        private string mStrPath = string.Empty;

        private bool mIsConnected = false;

        private FtpMode mMode = FtpMode.Passive;

        private FtpSystemType mSystemType = FtpSystemType.UNIX;

        private string mStrReply = string.Empty;

        private int mIntReplyCode = 0;

        private static int BLOCK_SIZE = 2048;

        private byte[] mBuffer = new byte[FtpClient.BLOCK_SIZE];

 

        private event FtpLogEventHandler mFtpLogEvent;

        public event FtpLogEventHandler FtpLogEvent

        {

            add

            {

                FtpLogEventHandler handlerTemp;

                FtpLogEventHandler fieldsChanged = this.mFtpLogEvent;

                do

                {

                    handlerTemp = fieldsChanged;

                    FtpLogEventHandler handlerRes =    (FtpLogEventHandler)Delegate.Combine(handlerTemp, value);

                    fieldsChanged = Interlocked.CompareExchange<FtpLogEventHandler>(ref this.mFtpLogEvent, handlerRes, handlerTemp);

                }

                while (fieldsChanged != handlerTemp);

            }

 

            remove

            {

                FtpLogEventHandler handlerTemp;

                FtpLogEventHandler fieldsChanged = this.mFtpLogEvent;

                do

                {

                    handlerTemp = fieldsChanged;

                    FtpLogEventHandler handlerRes = (FtpLogEventHandler)Delegate.Remove(handlerTemp, value);

                    fieldsChanged = Interlocked.CompareExchange<FtpLogEventHandler>(ref this.mFtpLogEvent, handlerRes, handlerTemp);

                }

                while (fieldsChanged != handlerTemp);

            }

        }

 

        private event FtpTranProgressEventHandler mFtpTranProgressEvent;

        public event FtpTranProgressEventHandler FtpTranProgressEvent

        {

            add

            {

                FtpTranProgressEventHandler handlerTemp;

                FtpTranProgressEventHandler fieldsChanged = this.mFtpTranProgressEvent;

                do

                {

                    handlerTemp = fieldsChanged;

                    FtpTranProgressEventHandler handlerRes = (FtpTranProgressEventHandler)Delegate.Combine(handlerTemp, value);

                    fieldsChanged = Interlocked.CompareExchange<FtpTranProgressEventHandler>(ref this.mFtpTranProgressEvent, handlerRes, handlerTemp);

                }

                while (fieldsChanged != handlerTemp);

            }

            remove

            {

                FtpTranProgressEventHandler handlerTemp;

                FtpTranProgressEventHandler fieldsChanged = this.mFtpTranProgressEvent;

                do

                {

                    handlerTemp = fieldsChanged;

                    FtpTranProgressEventHandler handlerRes = (FtpTranProgressEventHandler)Delegate.Remove(handlerTemp, value);

                    fieldsChanged = Interlocked.CompareExchange<FtpTranProgressEventHandler>(ref this.mFtpTranProgressEvent, handlerRes, handlerTemp);

                }

                while (fieldsChanged != handlerTemp);

            }

        }

        public bool Connected

        {

            get

            {

                return this.mIsConnected;

            }

        }

        public FtpTransferType TransferType

        {

            set

            {

                if (value == FtpTransferType.Binary)

                {

                    this.SendCommand("TYPE I");

                }

                else

                {

                    this.SendCommand("TYPE A");

                }

                if (this.mIntReplyCode != 200)

                {

                    throw new IOException(this.mStrReply.Substring(4));

                }

            }

        }

        public FtpMode Mode

        {

            get

            {

                return this.mMode;

            }

            set

            {

                this.mMode = value;

            }

        }

        public FtpSystemType SystemType

        {

            get

            {

                return this.mSystemType;

            }

            set

            {

                this.mSystemType = value;

            }

        }

        protected virtual void OnFtpLogEvent(FtpLogEventArgs e)

        {

            if (this.mFtpLogEvent != null)

            {

                this.mFtpLogEvent(this, e);

            }

        }

        protected virtual void OnFtpTranProgressEvent(FtpTranProgressEventArgs e)

        {

            if (this.mFtpTranProgressEvent != null)

            {

                this.mFtpTranProgressEvent(this, e);

            }

        }

//ftp client

        public FtpClient(string server, string path, string user, string password, int port, FtpClient.FtpMode mode)

        {

            this.mStrServer = server;

            this.mStrPath = path;

            this.mStrUser = user;

            this.mStrPassword = password;

            this.mIntPort = port;

            this.mMode = mode;

        }

//socket connect连接

        public void Connect()

        {

            this.mSocketConnect = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPHostEntry ipHost = Dns.GetHostEntry(this.mStrServer);

            IPEndPoint iPEndPoint = new IPEndPoint(ipHost.AddressList[0], this.mIntPort);

            try

            {

                this.mSocketConnect.Connect(iPEndPoint);

            }

            catch (Exception)

            {

                throw new IOException("Couldn't connect to remote server");

            }

            this.ReadReply();

            if (this.mIntReplyCode != 220)

            {

                this.DisConnect();

                throw new IOException(this.mStrReply.Substring(4));

            }

            this.SendCommand("USER " + this.mStrUser);

            if (this.mIntReplyCode != 331 && this.mIntReplyCode != 230)

            {

                this.CloseSocketConnect();

                throw new IOException(this.mStrReply.Substring(4));

            }

            if (this.mIntReplyCode == 331)

            {

                this.SendCommand("PASS " + this.mStrPassword);

                if (this.mIntReplyCode != 230 && this.mIntReplyCode != 202)

                {

                    this.CloseSocketConnect();

                    throw new IOException(this.mStrReply.Substring(4));

                }

            }

            this.SendCommand("SYST");

            if (this.mIntReplyCode != 215)

            {

                this.CloseSocketConnect();

                throw new IOException(this.mStrReply.Substring(4));

            }

 

            if (this.mStrReply[4].ToString() == "W" || this.mStrReply[4].ToString() == "w")

            {

                this.mSystemType = FtpClient.FtpSystemType.WINDOWS;

            }

            this.mIsConnected = true;

            this.ChDir(this.mStrPath);

        }

        public void DisConnect()

        {

            this.CloseSocketConnect();

        }

        public void ChDir(string strDirName)

        {

            if (strDirName.Equals(""))

            {

                return;

            }

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            this.SendCommand("CWD " + strDirName);

            if (this.mIntReplyCode != 250)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

            this.mStrPath = strDirName;

        }

        public void Reset(long size)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            this.SendCommand("REST " + size.ToString());

            if (this.mIntReplyCode != 350)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

        }

 

        public string[] Dir(string strMark)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            char[] array = new char[]

            {

                '\n'

            };

            string text;

            string[] result;

            if (this.mMode == FtpClient.FtpMode.Active)

            {

                TcpListener tcpListener = null;

                this.CreateDataListener(ref tcpListener);

                this.TransferType = FtpClient.FtpTransferType.ASCII;

                this.SendCommand("LIST");

                Socket socket = tcpListener.AcceptSocket();

                text = "";

                int num;

//socket receive

                do

                {

                    num = socket.Receive(this.mBuffer, this.mBuffer.Length, 0);

                    text += Encoding.Default.GetString(this.mBuffer, 0, num);

                }

                while (num >= this.mBuffer.Length);

                result = text.Split(array);

                socket.Close();

                tcpListener.Stop();

                return result;

            }

//send command =List

            Socket socket2 = this.CreateDataSocket();

            this.SendCommand("LIST");

            if (this.mIntReplyCode != 150 && this.mIntReplyCode != 125 && this.mIntReplyCode != 226)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

            text = "";

            int num2;

//socket2 receive

            do

            {

                num2 = socket2.Receive(this.mBuffer, this.mBuffer.Length, 0);

                text += Encoding.Default.GetString(this.mBuffer, 0, num2);

            }

            while (num2 >= this.mBuffer.Length);

            result = text.Split(array);

            socket2.Close();

            if (this.mIntReplyCode != 226)

            {

                this.ReadReply();

                if (this.mIntReplyCode != 226)

                {

                    throw new IOException(this.mStrReply.Substring(4));

                }

            }

            return result;

        }

//Upload File

        public void UploadFile(string strFile)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            if (this.mMode == FtpClient.FtpMode.Active)

            {

                TcpListener tcpListener = null;

                this.CreateDataListener(ref tcpListener);

                this.TransferType = FtpClient.FtpTransferType.Binary;

                this.SendCommand("STOR " + Path.GetFileName(strFile));

                if (this.mIntReplyCode != 125 && this.mIntReplyCode != 150)

                {

                    throw new IOException(this.mStrReply.Substring(4));

                }

                Socket socket = tcpListener.AcceptSocket();

                FileStream fileStream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                long length = fileStream.Length;

                long num = 0L;

                int num2;

//filestream read

                while ((num2 = fileStream.Read(this.mBuffer, 0, this.mBuffer.Length)) > 0)

                {

                    num += (long)num2;

                    uint percent = (uint)(num * 100L / length);

                    FtpClient.FtpTranProgressEventArgs e = new FtpClient.FtpTranProgressEventArgs(percent);

                    this.OnFtpTranProgressEvent(e);

                    socket.Send(this.mBuffer, num2, 0);

                }

                fileStream.Close();

                if (socket.Connected)

                {

                    socket.Close();

                }

                tcpListener.Stop();

                return;

            }

            else

            {

                Socket socket2 = this.CreateDataSocket();

                this.SendCommand("STOR " + Path.GetFileName(strFile));

                if (this.mIntReplyCode != 125 && this.mIntReplyCode != 150)

                {

                    throw new IOException(this.mStrReply.Substring(4));

                }

                FileStream fileStream2 = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                long length = fileStream2.Length;

                long num = 0L;

                int num2;

                while ((num2 = fileStream2.Read(this.mBuffer, 0, this.mBuffer.Length)) > 0)

                {

                    num += (long)num2;

                    uint percent = (uint)(num * 100L / length);

                    FtpClient.FtpTranProgressEventArgs e2 = new FtpClient.FtpTranProgressEventArgs(percent);

                    this.OnFtpTranProgressEvent(e2);

                    socket2.Send(this.mBuffer, num2, 0);

                }

                fileStream2.Close();

                if (socket2.Connected)

                {

                    socket2.Close();

                }

                if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                {

                    this.ReadReply();

                    if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                    {

                        throw new IOException(this.mStrReply.Substring(4));

                    }

                }

                return;

            }

        }

//Download File

        public void DownloadFile(string strRemoteFileName, string strLocalFolder, string strLocalFileName)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

//判断this.mMode

            if (this.mMode == FtpClient.FtpMode.Active)

            {

                TcpListener tcpListener = null;

                this.CreateDataListener(ref tcpListener);

                string extension = Path.GetExtension(strRemoteFileName);

                if (extension != ".txt" && extension != ".TXT")

                {

                    this.TransferType = FtpClient.FtpTransferType.Binary;

                }

                if (strLocalFileName == "")

                {

                    strLocalFileName = strRemoteFileName;

                }

                FileStream fileStream = new FileStream(strLocalFolder + "\\" + strLocalFileName, FileMode.Create);

                this.SendCommand("RETR " + strRemoteFileName);

                if (this.mIntReplyCode != 150 && this.mIntReplyCode != 125 && this.mIntReplyCode != 226 && this.mIntReplyCode != 250 && this.mIntReplyCode != 200)

                {

                    fileStream.Close();

                    throw new IOException(this.mStrReply.Substring(4));

                }

                Socket socket = tcpListener.AcceptSocket();

                while (true)

                {

                    int num = socket.Receive(this.mBuffer, this.mBuffer.Length, 0);

                    if (num <= 0)

                    {

                        break;

                    }

                    fileStream.Write(this.mBuffer, 0, num);

                }

                fileStream.Close();

                if (socket.Connected)

                {

                    socket.Close();

                }

                if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                {

                    this.ReadReply();

                    if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                    {

                        throw new IOException(this.mStrReply.Substring(4));

                    }

                }

                tcpListener.Stop();

                return;

            }

            else

            {

                string extension2 = Path.GetExtension(strRemoteFileName);

                if (extension2 != ".txt" && extension2 != ".TXT")

                {

                    this.TransferType = FtpClient.FtpTransferType.Binary;

                }

                if (strLocalFileName == "")

                {

                    strLocalFileName = strRemoteFileName;

                }

                FileStream fileStream2 = new FileStream(strLocalFolder + "\\" + strLocalFileName, FileMode.Create);

                Socket socket2 = this.CreateDataSocket();

                this.SendCommand("RETR " + strRemoteFileName);

                if (this.mIntReplyCode != 150 && this.mIntReplyCode != 125 && this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                {

                    fileStream2.Close();

                    throw new IOException(this.mStrReply.Substring(4));

                }

                while (true)

                {

                    int num2 = socket2.Receive(this.mBuffer, this.mBuffer.Length, 0);

                    if (num2 <= 0)

                    {

                        break;

                    }

                    fileStream2.Write(this.mBuffer, 0, num2);

                }

                fileStream2.Close();

                if (socket2.Connected)

                {

                    socket2.Close();

                }

                if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                {

                    this.ReadReply();

                    if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)

                    {

                        throw new IOException(this.mStrReply.Substring(4));

                    }

                }

                return;

            }

        }

//create Dir

        public void CreateDir(string strDirName)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            this.SendCommand("MKD " + strDirName);

            if (this.mIntReplyCode != 257)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

        }

 

//delete Dir

        public void DeleteDir(string strDirName)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            this.SendCommand("RMD " + strDirName);

            if (this.mIntReplyCode != 250)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

        }

 

//delete file

        public void DeleteFile(string strFile)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            this.SendCommand("DELE " + strFile);

            if (this.mIntReplyCode != 250)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

        }

//get file size

        private long GetFileSize(string strFileName)

        {

            if (!this.mIsConnected)

            {

                this.Connect();

            }

            this.SendCommand("SIZE " + Path.GetFileName(strFileName));

            if (this.mIntReplyCode == 213 || this.mIntReplyCode == 200)

            {

                return long.Parse(this.mStrReply.Substring(4));

            }

            throw new IOException(this.mStrReply.Substring(4));

        }

        private string ReadLine()

        {

            string text = string.Empty;

            Thread.Sleep(200);

            int num;

            do

            {

                text = "";

                num = this.mSocketConnect.Receive(this.mBuffer, this.mBuffer.Length, 0);

                text += Encoding.Default.GetString(this.mBuffer, 0, num);

                FtpLogEventArgs e = new FtpLogEventArgs("应答:  " + text);

                this.OnFtpLogEvent(e);

            }

            while (num >= this.mBuffer.Length);

            char[] array = new char[]

            {

                '\n'

            };

            string[] array2 = text.Split(array);

            if (text.Length > 2)

            {

                text = array2[array2.Length - 2];

            }

            else

            {

                text = array2[0];

            }

            if (!text.Substring(3, 1).Equals(" "))

            {

                return this.ReadLine();

            }

            return text;

        }

//read reply

        private void ReadReply()

        {

            this.mStrReply = this.ReadLine();

            this.mIntReplyCode = int.Parse(this.mStrReply.Substring(0, 3));

        }

//send command

        private void SendCommand(string strCommand)

        {

            FtpLogEventArgs e = new FtpLogEventArgs("命令:  " + strCommand);

            this.OnFtpLogEvent(e);

            byte[] bytes = Encoding.Default.GetBytes((strCommand + "\r\n").ToCharArray());

            this.mSocketConnect.Send(bytes, bytes.Length, 0);

            this.ReadReply();

        }

//close socket connect

        private void CloseSocketConnect()

        {

            if (this.mSocketConnect != null)

            {

                this.mSocketConnect.Close();

                this.mSocketConnect = null;

            }

            this.mIsConnected = false;

        }

//create data socket

        private Socket CreateDataSocket()

        {

            Socket result;

            try

            {

                this.SendCommand("PASV");

                if (this.mIntReplyCode != 227)

                {

                    throw new IOException(this.mStrReply.Substring(4));

                }

                int num = this.mStrReply.IndexOf('(');

                int num2 = this.mStrReply.IndexOf(')');

                string text = this.mStrReply.Substring(num + 1, num2 - num - 1);

                string[] array = new string[6];

                array = text.Split(new char[]

                {

                    ','

                });

                if (array.Length != 6)

                {

                    throw new IOException("Malformed PASV strReply: " + this.mStrReply);

                }

                string text2 = string.Concat(new string[]

                {

                    array[0],

                    ".",

                    array[1],

                    ".",

                    array[2],

                    ".",

                    array[3]

                });

                try

                {

                    num = int.Parse(array[4]);

                    num2 = int.Parse(array[5]);

                }

                catch

                {

                    throw new IOException("Malformed PASV strReply: " + this.mStrReply);

                }

                int num3 = (num << 8) + num2;

                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(text2), num3);

                try

                {

                    socket.Connect(iPEndPoint);

                }

                catch (Exception)

                {

                    throw new IOException("Can't connect to remote server");

                }

                result = socket;

            }

            catch (Exception ex)

            {

                throw new Exception(ex.ToString());

            }

            return result;

        }

//create data listener

        private void CreateDataListener(ref TcpListener listener)

        {

            string hostName = Dns.GetHostName();

            IPAddress iPAddress = Dns.GetHostEntry(hostName).AddressList[0];

            listener = new TcpListener(iPAddress, 0);

            listener.Start();

            IPEndPoint iPEndPoint = (IPEndPoint)listener.LocalEndpoint;

            int num = iPEndPoint.Port >> 8;

            int num2 = iPEndPoint.Port & 255;

            this.SendCommand(string.Concat(new string[]

            {

                "PORT ",

                iPEndPoint.Address.ToString().Replace(".", ","),

                ",",

                num.ToString(),

                ",",

                num2.ToString()

            }));

            if (this.mIntReplyCode != 200 && this.mIntReplyCode != 226)

            {

                throw new IOException(this.mStrReply.Substring(4));

            }

        }

}

简单使用

FtpClient ftpClient = new FtpClient(ip, "/", user, pass, 21, FtpClient.FtpMode.Passive);

ftpClient.FtpTranProgressEvent += (s, e) =>

{

    progress.Value = (int)e.Percent;

    Application.DoEvents();

};

 

try

{

    ftpClient.Connect();

}

catch (Exception ex)

{

    ftpClient = null;

    return;

}

 

  if (ftpClient.Connected)

  {

      ftpClient.CreateDir(root);

      ftpClient.ChDir(root);

 

  try

  {

      ftpClient.UploadFile(@"D:\shin_angyo_onshi\Vol_SP\001.jpg");

  }

  catch (Exception ex)

  {

      MessageBox.Show(ex.Message.ToString());

      return;

  }

}

 

来自cnblog  kurodo

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值