Sockets ftp 下载出错,帮我看下 本帖最后由 jyqxj 于 2012-03-01 07:48:42 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 class FTPClient { private string strRemoteHost; private int strRemotePort; private string strRemotePath; private string strRemoteUser; private string strRemotePass; private Boolean bConnected; #region 内部变量 /// <summary> /// 服务器返回的应答信息(包含应答码) /// </summary> private string strMsg; /// <summary> /// 服务器返回的应答信息(包含应答码) /// </summary> private string strReply; /// <summary> /// 服务器返回的应答码 /// </summary> private int iReplyCode; /// <summary> /// 进行控制连接的socket /// </summary> private Socket socketControl; /// <summary> /// 传输模式 /// </summary> private TransferType trType; /// <summary> /// 传输模式:二进制类型、ASCII类型 /// </summary> public enum TransferType { /// <summary> /// Binary /// </summary> Binary, /// <summary> /// ASCII /// </summary> ASCII }; /// <summary> /// 接收和发送数据的缓冲区 /// </summary> private static int BLOCK_SIZE = 512; Byte[] buffer = new Byte[BLOCK_SIZE]; /// <summary> /// 编码方式 /// </summary> Encoding ASCII = Encoding.Default; #endregion #region 内部函数 #region 构造函数 /// <summary> /// 缺省构造函数 /// </summary> public FTPClient() { strRemoteHost = ""; strRemotePath = ""; strRemoteUser = ""; strRemotePass = ""; strRemotePort = 21; bConnected = false; } /// <summary> /// 构造函数 /// </summary> /// <param name="remoteHost"></param> /// <param name="remotePath"></param> /// <param name="remoteUser"></param> /// <param name="remotePass"></param> /// <param name="remotePort"></param> public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort) { IPAddress[] ips; ips = Dns.GetHostAddresses(remoteHost); strRemoteHost = ips[0].ToString(); strRemotePath = remotePath; strRemoteUser = remoteUser; strRemotePass = remotePass; strRemotePort = remotePort; Connect(); } #endregion #region 登陆 /// <summary> /// FTP服务器IP地址 /// </summary> public string RemoteHost { get { return strRemoteHost; } set { strRemoteHost = value; } } /// <summary> /// FTP服务器端口 /// </summary> public int RemotePort { get { return strRemotePort; } set { strRemotePort = value; } } /// <summary> /// 当前服务器目录 /// </summary> public string RemotePath { get { return strRemotePath; } set { strRemotePath = value; } } /// <summary> /// 登录用户账号 /// </summary> public string RemoteUser { set { strRemoteUser = value; } } /// <summary> /// 用户登录密码 /// </summary> public string RemotePass { set { strRemotePass = value; } } /// <summary> /// 是否登录 /// </summary> public bool Connected { get { return bConnected; } } #endregion #region 链接 /// <summary> /// 建立连接 /// </summary> public void Connect() { socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort); // 链接 try { socketControl.Connect(ep); } catch (Exception) { throw new IOException("Couldn't connect to remote server"); } // 获取应答码 ReadReply(); if (iReplyCode != 220) { DisConnect(); throw new IOException(strReply.Substring(4)); } // 登陆 SendCommand("USER " + strRemoteUser); if (!(iReplyCode == 331 || iReplyCode == 230)) { CloseSocketConnect();//关闭连接 throw new IOException(strReply.Substring(4)); } if (iReplyCode != 230) { //System.Diagnostics.Debug.WriteLine(iReplyCode); SendCommand("PASS " + strRemotePass); if (!(iReplyCode == 230 || iReplyCode == 202)) { CloseSocketConnect();//关闭连接 throw new IOException(strReply.Substring(4)); } } bConnected = true; // 切换到目录 ChDir(strRemotePath); } /// <summary> /// 关闭连接 /// </summary> public void DisConnect() { if (socketControl != null) { SendCommand("QUIT"); } CloseSocketConnect(); } #endregion #region 传输模式 /// <summary> /// 设置传输模式 /// </summary> /// <param name="ttType">传输模式</param> public void SetTransferType(TransferType ttType) { if (ttType == TransferType.Binary) { SendCommand("TYPE I");//binary类型传输 } else { SendCommand("TYPE A");//ASCII类型传输 } if (iReplyCode != 200) { throw new IOException(strReply.Substring(4)); } else { trType = ttType; } } /// <summary> /// 获得传输模式 /// </summary> /// <returns>传输模式</returns> public TransferType GetTransferType() { return trType; } #endregion #region 文件操作 /// <summary> /// 获得文件列表 /// </summary> /// <param name="strMask">文件名的匹配字符串</param> /// <returns></returns> public string[] Dir(string strMask) { // 建立链接 if (!bConnected) { Connect(); } //建立进行数据连接的socket Socket socketData = CreateDataSocket(); //传送命令 SendCommand("NLST " + strMask); if (iReplyCode == 550) { Put(strMask); SendCommand("NLST " + strMask); } //分析应答代码 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226)) { throw new IOException(strReply.Substring(4)); } //获得结果 strMsg = ""; while (true) { int iBytes = socketData.Receive(buffer, buffer.Length, 0); strMsg += ASCII.GetString(buffer, 0, iBytes); if (iBytes < buffer.Length) { break; } } strMsg = strMsg.Replace('\r',' '); char[] seperator = { '\n' }; string[] strsFileList = strMsg.Split(seperator); socketData.Close();//数据socket关闭时也会有返回码 if (iReplyCode != 226) { ReadReply(); if (iReplyCode != 226) { throw new IOException(strReply.Substring(4)); } } return strsFileList; } /// <summary> /// 获取文件大小 /// </summary> /// <param name="strFileName">文件名</param> /// <returns>文件大小</returns> private long GetFileSize(string strFileName) { if (!bConnected) { Connect(); } SendCommand("SIZE " + Path.GetFileName(strFileName)); long lSize = 0; if (iReplyCode == 213) { lSize = Int64.Parse(strReply.Substring(4)); } else { throw new IOException(strReply.Substring(4)); } return lSize; } /// <summary> /// 删除 /// </summary> /// <param name="strFileName">待删除文件名</param> public void Delete(string strFileName) { if (!bConnected) { Connect(); } SendCommand("DELE " + strFileName); if (iReplyCode != 250) { throw new IOException(strReply.Substring(4)); } } /// <summary> /// 重命名(如果新文件名与已有文件重名,将覆盖已有文件) /// </summary> /// <param name="strOldFileName">旧文件名</param> /// <param name="strNewFileName">新文件名</param> public void Rename(string strOldFileName, string strNewFileName) { if (!bConnected) { Connect(); } SendCommand("RNFR " + strOldFileName); if (iReplyCode != 350) { throw new IOException(strReply.Substring(4)); } // 如果新文件名与原有文件重名,将覆盖原有文件 SendCommand("RNTO " + strNewFileName); if (iReplyCode != 250) { throw new IOException(strReply.Substring(4)); } } #endregion #region 上传和下载 /// <summary> /// 下载一批文件 /// </summary> /// <param name="strFileNameMask">文件名的匹配字符串</param> /// <param name="strFolder">本地目录(不得以/结束)</param> public void Get(string strFileNameMask, string strFolder) { if (!bConnected) { Connect(); } string[] strFiles = Dir(strFileNameMask); foreach (string strFile in strFiles) { if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串 { Get(strFile, strFolder, strFile); } } } /// <summary> /// 下载一个文件 /// </summary> /// <param name="strRemoteFileName">要下载的文件名</param> /// <param name="strFolder">本地目录(不得以/结束)</param> /// <param name="strLocalFileName">保存在本地时的文件名</param> public void Get(string strRemoteFileName, string strFolder, string strLocalFileName) { if (!bConnected) { Connect(); } strRemoteFileName = strRemoteFileName.Trim(' '); //SetTransferType(TransferType.Binary); if (strLocalFileName.Equals("")) { strLocalFileName = strRemoteFileName; } /* if (!File.Exists(strLocalFileName)) { Stream st = File.Create(strLocalFileName); st.Close(); }*/ FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create); Socket socketData = CreateDataSocket(); SendCommand("RETR " + strRemoteFileName); if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250)) { return; throw new IOException(strReply.Substring(4)); } while (true) { int iBytes = socketData.Receive(buffer, buffer.Length, 0); output.Write(buffer, 0, iBytes); if (iBytes <= 0) { break; } } output.Close(); if (socketData.Connected) { socketData.Close(); } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { throw new IOException(strReply.Substring(4)); } } } /// <summary> /// 上传一批文件 /// </summary> /// <param name="strFolder">本地目录(不得以/结束)</param> /// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param> public void Put(string strFolder, string strFileNameMask) { string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask); foreach (string strFile in strFiles) { //strFile是完整的文件名(包含路径) Put(strFile); } } /// <summary> /// 上传一个文件 /// </summary> /// <param name="strFileName">本地文件名</param> public void Put(string strFileName) { if (!bConnected) { Connect(); } Socket socketData = CreateDataSocket(); SendCommand("STOR " + Path.GetFileName(strFileName)); if (!(iReplyCode == 125 || iReplyCode == 150)) { throw new IOException(strReply.Substring(4)); } FileStream input = new FileStream(strFileName, FileMode.Open); int iBytes = 0; while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0) { socketData.Send(buffer, iBytes, 0); } input.Close(); if (socketData.Connected) { socketData.Close(); } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { throw new IOException(strReply.Substring(4)); } } } #endregion #region 目录操作 /// <summary> /// 创建目录 /// </summary> /// <param name="strDirName">目录名</param> public void MkDir(string strDirName) { if (!bConnected) { Connect(); } SendCommand("MKD " + strDirName); if (iReplyCode != 257) { throw new IOException(strReply.Substring(4)); } } /// <summary> /// 删除目录 /// </summary> /// <param name="strDirName">目录名</param> public void RmDir(string strDirName) { if (!bConnected) { Connect(); } SendCommand("RMD " + strDirName); if (iReplyCode != 250) { throw new IOException(strReply.Substring(4)); } } /// <summary> /// 改变目录 /// </summary> /// <param name="strDirName">新的工作目录名</param> public void ChDir(string strDirName) { if (strDirName.Equals(".") || strDirName.Equals("")) { return; } if (!bConnected) { Connect(); } SendCommand("CWD " + strDirName); if (iReplyCode != 250) { throw new IOException(strReply.Substring(4)); } this.strRemotePath = strDirName; } /// <summary> /// 列目录 /// </summary> /// <param name="strDirName"></param> public string[] ListDir() { if (!bConnected) { Connect(); } //建立进行数据连接的socket Socket socketData = CreateDataSocket(); SendCommand("LIST"); if (iReplyCode != 150) { throw new IOException(strReply.Substring(4)); } //获得结果 strMsg = ""; while (true) { int iBytes = socketData.Receive(buffer, buffer.Length, 0); strMsg += ASCII.GetString(buffer, 0, iBytes); if (iBytes < buffer.Length) { break; } } strMsg = strMsg.Replace('\r', ' '); char[] seperator = { '\n' }; string[] strsFileList = strMsg.Split(seperator); socketData.Close();//数据socket关闭时也会有返回码 if (iReplyCode != 226) { ReadReply(); if (iReplyCode != 226) { throw new IOException(strReply.Substring(4)); } } return strsFileList; } #endregion /// <summary> /// 将一行应答字符串记录在strReply和strMsg /// 应答码记录在iReplyCode /// </summary> private void ReadReply() { strMsg = ""; strReply = ReadLine(); iReplyCode = Int32.Parse(strReply.Substring(0, 3)); } /// <summary> /// 建立进行数据连接的socket /// </summary> /// <returns>数据连接socket</returns> private Socket CreateDataSocket() { SendCommand("PASV"); if (iReplyCode != 227) { throw new IOException(strReply.Substring(4)); } int index1 = strReply.IndexOf('('); int index2 = strReply.IndexOf(')'); string ipData = strReply.Substring(index1 + 1, index2 - index1 - 1); int[] parts = new int[6]; int len = ipData.Length; int partCount = 0; string buf = ""; for (int i = 0; i < len && partCount <= 6; i++) { char ch = Char.Parse(ipData.Substring(i, 1)); if (Char.IsDigit(ch)) buf += ch; else if (ch != ',') { throw new IOException("Malformed PASV strReply: " + strReply); } if (ch == ',' || i + 1 == len) { try { parts[partCount++] = Int32.Parse(buf); buf = ""; } catch (Exception) { throw new IOException("Malformed PASV strReply: " + strReply); } } } string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3]; int port = (parts[4] << 8) + parts[5]; Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port); try { s.Connect(ep); } catch (Exception) { throw new IOException("Can't connect to remote server"); } return s; } /// <summary> /// 关闭socket连接(用于登录以前) /// </summary> private void CloseSocketConnect() { if (socketControl != null) { socketControl.Close(); socketControl = null; } bConnected = false; } /// <summary> /// 读取Socket返回的所有字符串 /// </summary> /// <returns>包含应答码的字符串行</returns> private string ReadLine() { System.Diagnostics.Debug.WriteLine("a"); string str1=""; while (true) { System.Diagnostics.Debug.WriteLine("b"); int iBytes = socketControl.Receive(buffer, buffer.Length, 0); strMsg += ASCII.GetString(buffer, 0, iBytes); str1 += ASCII.GetString(buffer, 0, iBytes); if (iBytes < buffer.Length) { break; } } char[] seperator = { '\n' }; string[] mess = strMsg.Split(seperator); if (strMsg.Length > 2) { strMsg = mess[mess.Length - 2]; //seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串, //但也会分配为空字符串给后面(也是最后一个)字符串数组, //所以最后一个mess是没用的空字符串 //但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格 } else { strMsg = mess[0]; } System.Diagnostics.Debug.WriteLine(strMsg); System.Diagnostics.Debug.WriteLine(str1); if (!str1.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串) { System.Diagnostics.Debug.WriteLine("s"); return ReadLine(); } return strMsg; } /// <summary> /// 发送命令并获取应答码和最后一行应答字符串 /// </summary> /// <param name="strCommand">命令</param> private void SendCommand(string strCommand) { Byte[] cmdBytes = ASCII.GetBytes((strCommand + "\r\n").ToCharArray()); socketControl.Send(cmdBytes, cmdBytes.Length, 0); ReadReply(); } #endregion 关于窗口类的疑问 关于汉字向Unicode的转换. 基于xml动态界面设计 将DataTable中的两列合并,有没有比较简单的办法? 类的属性是变化的能否实现 求线程控制显示不同的图片 在线等:一个很大的文本文件。如何在其后面第3个字符位置插入一段文本?和如何计算字符串的字节数? textbox [winform] 引入DLL问题 100分,思归等高手进~ httpruntime 缓存的问题,在线等 读取dll乱码问题 vs.net 前台后台数组调用
class FTPClient
{
private string strRemoteHost;
private int strRemotePort;
private string strRemotePath;
private string strRemoteUser;
private string strRemotePass;
private Boolean bConnected; #region 内部变量
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string strMsg;
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string strReply;
/// <summary>
/// 服务器返回的应答码
/// </summary>
private int iReplyCode;
/// <summary>
/// 进行控制连接的socket
/// </summary>
private Socket socketControl;
/// <summary>
/// 传输模式
/// </summary>
private TransferType trType;
/// <summary>
/// 传输模式:二进制类型、ASCII类型
/// </summary>
public enum TransferType
{
/// <summary>
/// Binary
/// </summary>
Binary,
/// <summary>
/// ASCII
/// </summary>
ASCII
};
/// <summary>
/// 接收和发送数据的缓冲区
/// </summary>
private static int BLOCK_SIZE = 512;
Byte[] buffer = new Byte[BLOCK_SIZE];
/// <summary>
/// 编码方式
/// </summary>
Encoding ASCII = Encoding.Default;
#endregion #region 内部函数
#region 构造函数
/// <summary>
/// 缺省构造函数
/// </summary>
public FTPClient()
{
strRemoteHost = "";
strRemotePath = "";
strRemoteUser = "";
strRemotePass = "";
strRemotePort = 21;
bConnected = false;
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="remoteHost"></param>
/// <param name="remotePath"></param>
/// <param name="remoteUser"></param>
/// <param name="remotePass"></param>
/// <param name="remotePort"></param>
public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
{
IPAddress[] ips; ips = Dns.GetHostAddresses(remoteHost);
strRemoteHost = ips[0].ToString();
strRemotePath = remotePath;
strRemoteUser = remoteUser;
strRemotePass = remotePass;
strRemotePort = remotePort;
Connect();
}
#endregion #region 登陆
/// <summary>
/// FTP服务器IP地址
/// </summary> public string RemoteHost
{
get
{
return strRemoteHost;
}
set
{
strRemoteHost = value;
}
}
/// <summary>
/// FTP服务器端口
/// </summary>
public int RemotePort
{
get
{
return strRemotePort;
}
set
{
strRemotePort = value;
}
}
/// <summary>
/// 当前服务器目录
/// </summary>
public string RemotePath
{
get
{
return strRemotePath;
}
set
{
strRemotePath = value;
}
}
/// <summary>
/// 登录用户账号
/// </summary>
public string RemoteUser
{
set
{
strRemoteUser = value;
}
}
/// <summary>
/// 用户登录密码
/// </summary>
public string RemotePass
{
set
{
strRemotePass = value;
}
} /// <summary>
/// 是否登录
/// </summary>
public bool Connected
{
get
{
return bConnected;
}
}
#endregion #region 链接
/// <summary>
/// 建立连接
/// </summary>
public void Connect()
{
socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
// 链接
try
{
socketControl.Connect(ep);
}
catch (Exception)
{
throw new IOException("Couldn't connect to remote server");
} // 获取应答码
ReadReply();
if (iReplyCode != 220)
{
DisConnect();
throw new IOException(strReply.Substring(4));
} // 登陆
SendCommand("USER " + strRemoteUser);
if (!(iReplyCode == 331 || iReplyCode == 230))
{
CloseSocketConnect();//关闭连接
throw new IOException(strReply.Substring(4));
}
if (iReplyCode != 230)
{
//System.Diagnostics.Debug.WriteLine(iReplyCode);
SendCommand("PASS " + strRemotePass);
if (!(iReplyCode == 230 || iReplyCode == 202))
{
CloseSocketConnect();//关闭连接
throw new IOException(strReply.Substring(4));
}
}
bConnected = true;
// 切换到目录
ChDir(strRemotePath);
}
/// <summary>
/// 关闭连接
/// </summary>
public void DisConnect()
{
if (socketControl != null)
{
SendCommand("QUIT");
}
CloseSocketConnect();
} #endregion #region 传输模式 /// <summary>
/// 设置传输模式
/// </summary>
/// <param name="ttType">传输模式</param>
public void SetTransferType(TransferType ttType)
{
if (ttType == TransferType.Binary)
{
SendCommand("TYPE I");//binary类型传输
}
else
{
SendCommand("TYPE A");//ASCII类型传输
}
if (iReplyCode != 200)
{
throw new IOException(strReply.Substring(4));
}
else
{
trType = ttType;
}
}
/// <summary>
/// 获得传输模式
/// </summary>
/// <returns>传输模式</returns>
public TransferType GetTransferType()
{
return trType;
} #endregion
#region 文件操作
/// <summary>
/// 获得文件列表
/// </summary>
/// <param name="strMask">文件名的匹配字符串</param>
/// <returns></returns>
public string[] Dir(string strMask)
{
// 建立链接
if (!bConnected)
{
Connect();
} //建立进行数据连接的socket
Socket socketData = CreateDataSocket(); //传送命令
SendCommand("NLST " + strMask);
if (iReplyCode == 550)
{
Put(strMask);
SendCommand("NLST " + strMask);
}
//分析应答代码
if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
{
throw new IOException(strReply.Substring(4));
} //获得结果
strMsg = "";
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
strMsg += ASCII.GetString(buffer, 0, iBytes);
if (iBytes < buffer.Length)
{
break;
}
}
strMsg = strMsg.Replace('\r',' ');
char[] seperator = { '\n' };
string[] strsFileList = strMsg.Split(seperator);
socketData.Close();//数据socket关闭时也会有返回码
if (iReplyCode != 226)
{
ReadReply();
if (iReplyCode != 226)
{
throw new IOException(strReply.Substring(4));
}
}
return strsFileList;
}
/// <summary>
/// 获取文件大小
/// </summary>
/// <param name="strFileName">文件名</param>
/// <returns>文件大小</returns>
private long GetFileSize(string strFileName)
{
if (!bConnected)
{
Connect();
}
SendCommand("SIZE " + Path.GetFileName(strFileName));
long lSize = 0;
if (iReplyCode == 213)
{
lSize = Int64.Parse(strReply.Substring(4));
}
else
{
throw new IOException(strReply.Substring(4));
}
return lSize;
}
/// <summary>
/// 删除
/// </summary>
/// <param name="strFileName">待删除文件名</param>
public void Delete(string strFileName)
{
if (!bConnected)
{
Connect();
}
SendCommand("DELE " + strFileName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
/// <summary>
/// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
/// </summary>
/// <param name="strOldFileName">旧文件名</param>
/// <param name="strNewFileName">新文件名</param>
public void Rename(string strOldFileName, string strNewFileName)
{
if (!bConnected)
{
Connect();
}
SendCommand("RNFR " + strOldFileName);
if (iReplyCode != 350)
{
throw new IOException(strReply.Substring(4));
}
// 如果新文件名与原有文件重名,将覆盖原有文件
SendCommand("RNTO " + strNewFileName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
#endregion #region 上传和下载
/// <summary>
/// 下载一批文件
/// </summary>
/// <param name="strFileNameMask">文件名的匹配字符串</param>
/// <param name="strFolder">本地目录(不得以/结束)</param>
public void Get(string strFileNameMask, string strFolder)
{
if (!bConnected)
{
Connect();
}
string[] strFiles = Dir(strFileNameMask);
foreach (string strFile in strFiles)
{
if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
{
Get(strFile, strFolder, strFile);
}
}
}
/// <summary>
/// 下载一个文件
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以/结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)
{
if (!bConnected)
{
Connect();
}
strRemoteFileName = strRemoteFileName.Trim(' ');
//SetTransferType(TransferType.Binary);
if (strLocalFileName.Equals(""))
{
strLocalFileName = strRemoteFileName;
}
/*
if (!File.Exists(strLocalFileName))
{
Stream st = File.Create(strLocalFileName);
st.Close();
}*/
FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
Socket socketData = CreateDataSocket();
SendCommand("RETR " + strRemoteFileName);
if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250))
{
return;
throw new IOException(strReply.Substring(4));
}
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
output.Write(buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
}
/// <summary>
/// 上传一批文件
/// </summary>
/// <param name="strFolder">本地目录(不得以/结束)</param>
/// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
public void Put(string strFolder, string strFileNameMask)
{
string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask);
foreach (string strFile in strFiles)
{
//strFile是完整的文件名(包含路径)
Put(strFile);
}
}
/// <summary>
/// 上传一个文件
/// </summary>
/// <param name="strFileName">本地文件名</param>
public void Put(string strFileName)
{
if (!bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand("STOR " + Path.GetFileName(strFileName));
if (!(iReplyCode == 125 || iReplyCode == 150))
{
throw new IOException(strReply.Substring(4));
}
FileStream input = new
FileStream(strFileName, FileMode.Open);
int iBytes = 0;
while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
socketData.Send(buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
} #endregion
#region 目录操作
/// <summary>
/// 创建目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void MkDir(string strDirName)
{
if (!bConnected)
{
Connect();
}
SendCommand("MKD " + strDirName);
if (iReplyCode != 257)
{
throw new IOException(strReply.Substring(4));
}
}
/// <summary>
/// 删除目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void RmDir(string strDirName)
{
if (!bConnected)
{
Connect();
}
SendCommand("RMD " + strDirName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
/// <summary>
/// 改变目录
/// </summary>
/// <param name="strDirName">新的工作目录名</param>
public void ChDir(string strDirName)
{
if (strDirName.Equals(".") || strDirName.Equals(""))
{
return;
}
if (!bConnected)
{
Connect();
}
SendCommand("CWD " + strDirName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
this.strRemotePath = strDirName;
} /// <summary>
/// 列目录
/// </summary>
/// <param name="strDirName"></param>
public string[] ListDir()
{
if (!bConnected)
{
Connect();
}
//建立进行数据连接的socket
Socket socketData = CreateDataSocket();
SendCommand("LIST");
if (iReplyCode != 150)
{
throw new IOException(strReply.Substring(4));
}
//获得结果
strMsg = "";
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
strMsg += ASCII.GetString(buffer, 0, iBytes);
if (iBytes < buffer.Length)
{
break;
}
}
strMsg = strMsg.Replace('\r', ' ');
char[] seperator = { '\n' };
string[] strsFileList = strMsg.Split(seperator);
socketData.Close();//数据socket关闭时也会有返回码
if (iReplyCode != 226)
{
ReadReply();
if (iReplyCode != 226)
{
throw new IOException(strReply.Substring(4));
}
}
return strsFileList;
}
#endregion
/// <summary>
/// 将一行应答字符串记录在strReply和strMsg
/// 应答码记录在iReplyCode
/// </summary>
private void ReadReply()
{
strMsg = "";
strReply = ReadLine(); iReplyCode = Int32.Parse(strReply.Substring(0, 3));
} /// <summary>
/// 建立进行数据连接的socket
/// </summary>
/// <returns>数据连接socket</returns>
private Socket CreateDataSocket()
{
SendCommand("PASV");
if (iReplyCode != 227)
{
throw new IOException(strReply.Substring(4));
}
int index1 = strReply.IndexOf('(');
int index2 = strReply.IndexOf(')');
string ipData =
strReply.Substring(index1 + 1, index2 - index1 - 1);
int[] parts = new int[6];
int len = ipData.Length;
int partCount = 0;
string buf = "";
for (int i = 0; i < len && partCount <= 6; i++)
{
char ch = Char.Parse(ipData.Substring(i, 1));
if (Char.IsDigit(ch))
buf += ch;
else if (ch != ',')
{
throw new IOException("Malformed PASV strReply: " +
strReply);
}
if (ch == ',' || i + 1 == len)
{
try
{
parts[partCount++] = Int32.Parse(buf);
buf = "";
}
catch (Exception)
{
throw new IOException("Malformed PASV strReply: " +
strReply);
}
}
}
string ipAddress = parts[0] + "." + parts[1] + "." +
parts[2] + "." + parts[3];
int port = (parts[4] << 8) + parts[5];
Socket s = new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new
IPEndPoint(IPAddress.Parse(ipAddress), port);
try
{
s.Connect(ep);
}
catch (Exception)
{
throw new IOException("Can't connect to remote server");
}
return s;
}
/// <summary>
/// 关闭socket连接(用于登录以前)
/// </summary>
private void CloseSocketConnect()
{
if (socketControl != null)
{
socketControl.Close();
socketControl = null;
}
bConnected = false;
} /// <summary>
/// 读取Socket返回的所有字符串
/// </summary>
/// <returns>包含应答码的字符串行</returns>
private string ReadLine()
{
System.Diagnostics.Debug.WriteLine("a");
string str1="";
while (true)
{
System.Diagnostics.Debug.WriteLine("b");
int iBytes = socketControl.Receive(buffer, buffer.Length, 0);
strMsg += ASCII.GetString(buffer, 0, iBytes);
str1 += ASCII.GetString(buffer, 0, iBytes);
if (iBytes < buffer.Length)
{
break;
}
}
char[] seperator = { '\n' };
string[] mess = strMsg.Split(seperator);
if (strMsg.Length > 2)
{
strMsg = mess[mess.Length - 2];
//seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
//但也会分配为空字符串给后面(也是最后一个)字符串数组,
//所以最后一个mess是没用的空字符串
//但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
}
else
{
strMsg = mess[0];
}
System.Diagnostics.Debug.WriteLine(strMsg);
System.Diagnostics.Debug.WriteLine(str1);
if (!str1.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
{
System.Diagnostics.Debug.WriteLine("s");
return ReadLine();
}
return strMsg;
}
/// <summary>
/// 发送命令并获取应答码和最后一行应答字符串
/// </summary>
/// <param name="strCommand">命令</param>
private void SendCommand(string strCommand)
{
Byte[] cmdBytes = ASCII.GetBytes((strCommand + "\r\n").ToCharArray());
socketControl.Send(cmdBytes, cmdBytes.Length, 0);
ReadReply();
} #endregion