using system;
using system.net;
using system.io;
using system.text;
using system.net.sockets;
namespace zhangyuk.net.csdn.blog.ftpclient
{
/// <summary>
/// ftp client
/// </summary>
public class ftpclient
{
#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 )
{
strremotehost = remotehost;
strremotepath = remotepath;
strremoteuser = remoteuser;
strremotepass = remotepass;
strremoteport = remoteport;
connect();
}
#endregion
#region 登陆
/// <summary>
/// ftp服务器ip地址
/// </summary>
private string strremotehost;
public string remotehost
{
get
{
return strremotehost;
}
set
{
strremotehost = value;
}
}
/// <summary>
/// ftp服务器端口
/// </summary>
private int strremoteport;
public int remoteport
{
get
{
return strremoteport;
}
set
{
strremoteport = value;
}
}
/// <summary>
/// 当前服务器目录
/// </summary>
private string strremotepath;
public string remotepath
{
get
{
return strremotepath;
}
set
{
strremotepath = value;
}
}
/// <summary>
/// 登录用户账号
/// </summary>
private string strremoteuser;
public string remoteuser
{
set
{
strremoteuser = value;
}
}
/// <summary>
/// 用户登录密码
/// </summary>
private string strremotepass;
public string remotepass
{
set
{
strremotepass = value;
}
}
/// <summary>
/// 是否登录
/// </summary>
private boolean bconnected;
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(“couldnt 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 )
{
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>
/// 传输模式:二进制类型、ascii类型
/// </summary>
public enum transfertype {binary,ascii};
/// <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 == 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;
}
}
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();
}
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))
{
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;
}
#endregion
#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>
/// 接收和发送数据的缓冲区
/// </summary>
private static int block_size = 512;
byte[] buffer = new byte[block_size];
/// <summary>
/// 编码方式
/// </summary>
encoding ascii = encoding.ascii;
#endregion
#region 内部函数
/// <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(“cant 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()
{
while(true)
{
int ibytes = socketcontrol.receive(buffer, buffer.length, 0);
strmsg += 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];
}
if(!strmsg.substring(3,1).equals(” “))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
{
return readline();
}
return strmsg;
}
/// <summary>
/// 发送命令并获取应答码和最后一行应答字符串
/// </summary>
/// <param name=”strcommand”>命令</param>
private void sendcommand(string strcommand)
{
byte[] cmdbytes =
encoding.ascii.getbytes((strcommand+”\r\n”).tochararray());
socketcontrol.send(cmdbytes, cmdbytes.length, 0);
readreply();
}
#endregion
}
}
namespace zhangyuk.net.csdn.blog.ftpclient
{
/// <summary>
/// ftp client
/// </summary>
public class ftpclient
{
#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 )
{
strremotehost = remotehost;
strremotepath = remotepath;
strremoteuser = remoteuser;
strremotepass = remotepass;
strremoteport = remoteport;
connect();
}
#endregion
#region 登陆
/// <summary>
/// ftp服务器ip地址
/// </summary>
private string strremotehost;
public string remotehost
{
get
{
return strremotehost;
}
set
{
strremotehost = value;
}
}
/// <summary>
/// ftp服务器端口
/// </summary>
private int strremoteport;
public int remoteport
{
get
{
return strremoteport;
}
set
{
strremoteport = value;
}
}
/// <summary>
/// 当前服务器目录
/// </summary>
private string strremotepath;
public string remotepath
{
get
{
return strremotepath;
}
set
{
strremotepath = value;
}
}
/// <summary>
/// 登录用户账号
/// </summary>
private string strremoteuser;
public string remoteuser
{
set
{
strremoteuser = value;
}
}
/// <summary>
/// 用户登录密码
/// </summary>
private string strremotepass;
public string remotepass
{
set
{
strremotepass = value;
}
}
/// <summary>
/// 是否登录
/// </summary>
private boolean bconnected;
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(“couldnt 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 )
{
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>
/// 传输模式:二进制类型、ascii类型
/// </summary>
public enum transfertype {binary,ascii};
/// <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 == 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;
}
}
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();
}
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))
{
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;
}
#endregion
#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>
/// 接收和发送数据的缓冲区
/// </summary>
private static int block_size = 512;
byte[] buffer = new byte[block_size];
/// <summary>
/// 编码方式
/// </summary>
encoding ascii = encoding.ascii;
#endregion
#region 内部函数
/// <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(“cant 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()
{
while(true)
{
int ibytes = socketcontrol.receive(buffer, buffer.length, 0);
strmsg += 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];
}
if(!strmsg.substring(3,1).equals(” “))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
{
return readline();
}
return strmsg;
}
/// <summary>
/// 发送命令并获取应答码和最后一行应答字符串
/// </summary>
/// <param name=”strcommand”>命令</param>
private void sendcommand(string strcommand)
{
byte[] cmdbytes =
encoding.ascii.getbytes((strcommand+”\r\n”).tochararray());
socketcontrol.send(cmdbytes, cmdbytes.length, 0);
readreply();
}
#endregion
}
}