Ftp协议Socket实现

时间:2023-03-09 21:53:53
Ftp协议Socket实现

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

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

 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 = ;
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 = ;
private static int BLOCK_SIZE = ;
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 != )
{
throw new IOException(this.mStrReply.Substring());
}
}
}
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);
}
}
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;
}
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[], this.mIntPort);
try
{
this.mSocketConnect.Connect(iPEndPoint);
}
catch (Exception)
{
throw new IOException("Couldn't connect to remote server");
}
this.ReadReply();
if (this.mIntReplyCode != )
{
this.DisConnect();
throw new IOException(this.mStrReply.Substring());
}
this.SendCommand("USER " + this.mStrUser);
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
this.CloseSocketConnect();
throw new IOException(this.mStrReply.Substring());
}
if (this.mIntReplyCode == )
{
this.SendCommand("PASS " + this.mStrPassword);
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
this.CloseSocketConnect();
throw new IOException(this.mStrReply.Substring());
}
}
this.SendCommand("SYST");
if (this.mIntReplyCode != )
{
this.CloseSocketConnect();
throw new IOException(this.mStrReply.Substring());
} if (this.mStrReply[].ToString() == "W" || this.mStrReply[].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 != )
{
throw new IOException(this.mStrReply.Substring());
}
this.mStrPath = strDirName;
}
public void Reset(long size)
{
if (!this.mIsConnected)
{
this.Connect();
}
this.SendCommand("REST " + size.ToString());
if (this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
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;
do
{
num = socket.Receive(this.mBuffer, this.mBuffer.Length, );
text += Encoding.Default.GetString(this.mBuffer, , num);
}
while (num >= this.mBuffer.Length);
result = text.Split(array);
socket.Close();
tcpListener.Stop();
return result;
}
Socket socket2 = this.CreateDataSocket();
this.SendCommand("LIST");
if (this.mIntReplyCode != && this.mIntReplyCode != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
text = "";
int num2;
do
{
num2 = socket2.Receive(this.mBuffer, this.mBuffer.Length, );
text += Encoding.Default.GetString(this.mBuffer, , num2);
}
while (num2 >= this.mBuffer.Length);
result = text.Split(array);
socket2.Close();
if (this.mIntReplyCode != )
{
this.ReadReply();
if (this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
return result;
}
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 != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
Socket socket = tcpListener.AcceptSocket();
FileStream fileStream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
long length = fileStream.Length;
long num = 0L;
int num2;
while ((num2 = fileStream.Read(this.mBuffer, , this.mBuffer.Length)) > )
{
num += (long)num2;
uint percent = (uint)(num * 100L / length);
FtpClient.FtpTranProgressEventArgs e = new FtpClient.FtpTranProgressEventArgs(percent);
this.OnFtpTranProgressEvent(e);
socket.Send(this.mBuffer, num2, );
}
fileStream.Close();
if (socket.Connected)
{
socket.Close();
}
tcpListener.Stop();
return;
}
else
{
Socket socket2 = this.CreateDataSocket();
this.SendCommand("STOR " + Path.GetFileName(strFile));
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
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, , this.mBuffer.Length)) > )
{
num += (long)num2;
uint percent = (uint)(num * 100L / length);
FtpClient.FtpTranProgressEventArgs e2 = new FtpClient.FtpTranProgressEventArgs(percent);
this.OnFtpTranProgressEvent(e2);
socket2.Send(this.mBuffer, num2, );
}
fileStream2.Close();
if (socket2.Connected)
{
socket2.Close();
}
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
this.ReadReply();
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
return;
}
}
public void DownloadFile(string strRemoteFileName, string strLocalFolder, string strLocalFileName)
{
if (!this.mIsConnected)
{
this.Connect();
}
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 != && this.mIntReplyCode != && this.mIntReplyCode != && this.mIntReplyCode != && this.mIntReplyCode != )
{
fileStream.Close();
throw new IOException(this.mStrReply.Substring());
}
Socket socket = tcpListener.AcceptSocket();
while (true)
{
int num = socket.Receive(this.mBuffer, this.mBuffer.Length, );
if (num <= )
{
break;
}
fileStream.Write(this.mBuffer, , num);
}
fileStream.Close();
if (socket.Connected)
{
socket.Close();
}
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
this.ReadReply();
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
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 != && this.mIntReplyCode != && this.mIntReplyCode != && this.mIntReplyCode != )
{
fileStream2.Close();
throw new IOException(this.mStrReply.Substring());
}
while (true)
{
int num2 = socket2.Receive(this.mBuffer, this.mBuffer.Length, );
if (num2 <= )
{
break;
}
fileStream2.Write(this.mBuffer, , num2);
}
fileStream2.Close();
if (socket2.Connected)
{
socket2.Close();
}
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
this.ReadReply();
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
return;
}
} public void CreateDir(string strDirName)
{
if (!this.mIsConnected)
{
this.Connect();
}
this.SendCommand("MKD " + strDirName);
if (this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
} public void DeleteDir(string strDirName)
{
if (!this.mIsConnected)
{
this.Connect();
}
this.SendCommand("RMD " + strDirName);
if (this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
} public void DeleteFile(string strFile)
{
if (!this.mIsConnected)
{
this.Connect();
}
this.SendCommand("DELE " + strFile);
if (this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
private long GetFileSize(string strFileName)
{
if (!this.mIsConnected)
{
this.Connect();
}
this.SendCommand("SIZE " + Path.GetFileName(strFileName));
if (this.mIntReplyCode == || this.mIntReplyCode == )
{
return long.Parse(this.mStrReply.Substring());
}
throw new IOException(this.mStrReply.Substring());
}
private string ReadLine()
{
string text = string.Empty;
Thread.Sleep();
int num;
do
{
text = "";
num = this.mSocketConnect.Receive(this.mBuffer, this.mBuffer.Length, );
text += Encoding.Default.GetString(this.mBuffer, , 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 > )
{
text = array2[array2.Length - ];
}
else
{
text = array2[];
}
if (!text.Substring(, ).Equals(" "))
{
return this.ReadLine();
}
return text;
}
private void ReadReply()
{
this.mStrReply = this.ReadLine();
this.mIntReplyCode = int.Parse(this.mStrReply.Substring(, ));
}
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, );
this.ReadReply();
}
private void CloseSocketConnect()
{
if (this.mSocketConnect != null)
{
this.mSocketConnect.Close();
this.mSocketConnect = null;
}
this.mIsConnected = false;
}
private Socket CreateDataSocket()
{
Socket result;
try
{
this.SendCommand("PASV");
if (this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
int num = this.mStrReply.IndexOf('(');
int num2 = this.mStrReply.IndexOf(')');
string text = this.mStrReply.Substring(num + , num2 - num - );
string[] array = new string[];
array = text.Split(new char[]
{
','
});
if (array.Length != )
{
throw new IOException("Malformed PASV strReply: " + this.mStrReply);
}
string text2 = string.Concat(new string[]
{
array[],
".",
array[],
".",
array[],
".",
array[]
});
try
{
num = int.Parse(array[]);
num2 = int.Parse(array[]);
}
catch
{
throw new IOException("Malformed PASV strReply: " + this.mStrReply);
}
int num3 = (num << ) + 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;
}
private void CreateDataListener(ref TcpListener listener)
{
string hostName = Dns.GetHostName();
IPAddress iPAddress = Dns.GetHostEntry(hostName).AddressList[];
listener = new TcpListener(iPAddress, );
listener.Start();
IPEndPoint iPEndPoint = (IPEndPoint)listener.LocalEndpoint;
int num = iPEndPoint.Port >> ;
int num2 = iPEndPoint.Port & ;
this.SendCommand(string.Concat(new string[]
{
"PORT ",
iPEndPoint.Address.ToString().Replace(".", ","),
",",
num.ToString(),
",",
num2.ToString()
}));
if (this.mIntReplyCode != && this.mIntReplyCode != )
{
throw new IOException(this.mStrReply.Substring());
}
}
}

简单使用

 FtpClient ftpClient = new FtpClient(ip, "/", user, pass, , 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;
  }
}