以下代碼使用c#完成!完成。
using system;
using system.net.sockets;
/// <summary>
/// ftp 的摘要說明。
/// </summary>
public class ftp
{
public ftp()
{
//
// todo: 在此處添加構造函數邏輯
}
string _ser;
public string server
set{ _ser=value;}
get{return _ser;}
string _port;
public string port
set{_port=value;}
get{return _port;}
string _user;
public string user
set{ _user=value;}
get{return _user;}
string _pws;
public string password
set{ _pws=value;}
get{return _pws;}
bool _islog;
public bool islogined
set{ _islog=value;}
get{return _islog;}
int _msgid;
public int msgid
set{ _msgid=value;}
get{return _msgid;}
system.windows.forms.label _infx=new system.windows.forms.label() ;
public system.windows.forms.label infsshow
set{_infx=value;}
get{return _infx;}
system.windows.forms.listbox _infs=new system.windows.forms.listbox();
public system.windows.forms.listbox infslist
set{_infs=value;}
get{return _infs;}
system.windows.forms.progressbar _pb=new system.windows.forms.progressbar() ;
public system.windows.forms.progressbar progress
set{_pb=value;}
get{return _pb;}
public string nowinf;
system.net.sockets.tcpclient tcftp;
networkstream stm;
public bool login()
try
{
setinf("正在連接配接伺服器...");
tcftp=new tcpclient(_ser, system.convert.toint32(_port));//連接配接伺服器
stm= tcftp.getstream();//擷取網絡流
byte[] data=new byte[255];
int bytes;
setinf("等待伺服器就緒!");
bytes=stm.read(data,0,data.length);
string msg=system.text.encoding.ascii.getstring(data,0,bytes);//讀取登入成功的消息
if (msg.substring(0,3)=="220")
{
setinf(msg);
if (docmd("user " + _user+" ","331"))
{
if (docmd("pass " + _pws,"230"))
{
setinf("伺服器就緒!");
this.islogined=true;
return true;
}
setinf("密碼錯誤!",230);
return false;
}
setinf("使用者名錯誤",331);
return false;
}
else
setinf("伺服器沒有正确響應!",220);
}
catch (system.exception ex)
nowinf=ex.message ;
_infx.text=nowinf;
return false;
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="wait">比對前面的字元就可以了</param>
/// <returns></returns>
private bool docmd(string cmd,string wait)
string msg=docommand(cmd);
setinf(msg);
if (msg.indexof("/r/n")>=0)
string xx=msg.substring(msg.indexof("/r/n")) ;
msg=(xx=="/r/n"?msg:xx);
msg=msg.replace("/r/n","");
msg+="/r/n";
return (msg.substring(0,wait.length).tolower()==wait.tolower() );//如果msg的前部分是wait,則傳回成功.
private bool retok(string s1,string s2)
string msg=s1;
msg=msg.replace("/r/n","");
s1=msg+"/r/n";
return (s1.substring(0,s2.length).tolower()==s2.tolower() );//如果msg的前部分是wait,則傳回成功.
private string docommand(string cmd)
string msg=cmd;//+system.text.encoding.ascii.getstring(vbnull);
byte[] data=system.text.encoding.ascii.getbytes(msg+"/r/n");
stm.write(data,0,data.length);
system.windows.forms.application.doevents();
system.windows.forms.application.doevents();
data=new byte[255];
int bytes;
while(stm.dataavailable==false)
system.windows.forms.application.doevents() ;
nowinf="正在等待伺服器響應!";
bytes=stm.read(data,0,data.length);
msg=system.text.encoding.ascii.getstring(data,0,bytes);
return msg;
private void setinf(string msg)
if( msg.indexof("/r/n")>=0)
msg=msg.substring(0,msg.lastindexof("/r/n")-"/r/n".length );
msg+=" "+ system.datetime.now.timeofday.tostring();
nowinf=msg;
_infx.text=nowinf;
_infs.items.addrange(msg.split("/r/n".tochararray()));
_infs.selectedindex=_infs.items.count-1;
private void setinf(string msg,int msgid)
setinf(msg);
_msgid=msgid;
private string getmsg()
string msg;
byte[] data=new byte[1024];
while(stm.dataavailable==false)//如果沒有資訊可讀,等待伺服器響應.
bytes=stm.read(data,0,data.length);//讀取資料
msg=system.text.encoding.ascii.getstring(data,0,bytes);//轉換為字元
int rn= msg.indexof("/r/n",0);//查找換行符号
if (rn>0)
string mg=msg.substring(rn);//這裡是為了防止傳輸來多行資料,我試圖加大緩沖,也是這樣.
if( mg.length>2)//在這裡處理如同226這樣消息.
{ //前面一次傳回接受了一部分,第二次接受到了前面的一部分,在這裡用來分開他們
mg=mg.substring(2);
msg=mg;
/// 登出登入
/// <returns>成功時傳回真</returns>
public bool logout()
this.islogined=false;
bool ok=docmd("quit","221");
setinf("已斷開伺服器!",221);
return ok;
public bool setcurdir(string path)
if (docmd("cwd "+path,"250")==false)//"" is current directory.
setinf("确認目前目錄失敗!",257);
if (docmd("pwd "+path,"257")==false)//"" is current directory.
return true;
public string getcurdir()
string msg=docommand("pwd");
string[] st=msg.split((char)34);
return st[1];
public bool delete(string filename)
return docmd("dele "+filename,"250");
/// 上傳檔案
/// <param name="filename">要上傳的本地檔案</param>
/// <param name="svrpath">伺服器目标路徑.</param>
/// <returns>傳輸成功傳回真.</returns>
public bool uploadfile(string filename)
_pb.value=5;
if (this.islogined==false)
setinf("沒有連接配接到伺服器或沒有登入!");
if (docmd("type i","200")==false)//type set to i.
setinf("執行type i失敗!",200);
return false;
_pb.value=10;
string[] pt=filename.split("//".tochararray());
string filename=pt[pt.length-1] ;//svrpath+"/"+pt[pt.length-1] ;
string tmp1=docommand("size "+ filename);
setinf(tmp1);
if (retok(tmp1,"550")!=true)//50 /bbs/dv_forumnews/廣告.txt: no such file.
if (retok(tmp1,"501")!=true)
setinf("檔案已存在!",550);
return false;
setinf("檔案名為空,請指定檔案名!",501);
_pb.value=15;
if (docmd("mode s" ,"200")==false)//type set to i.
setinf("模式設定失敗!");
//return false;
/////擷取傳輸檔案的ip和段口
string tmp2 =docommand("pasv");
setinf(tmp2);
if (retok(tmp2,"227")==false)//type set to i.
setinf("伺服器沒有傳回227,無法知道端口,也無法開始傳輸檔案!",227);
string[] ips=getip( tmp2);
///////////////////
tcpclient tcm;
_pb.value=20;
setinf("正在連接配接檔案傳輸伺服器!");
tcm=new tcpclient(ips[0],system.convert.toint32(ips[1]));//連接配接傳輸伺服器.
catch (system.exception ex1)
setinf("連接配接檔案傳輸伺服器時出錯:ip位址:"+ips[0]+"端口:" + ips[1]+" 相關資訊:" + ex1.message );
if (docmd("stor "+ filename,"150")==false)//發送傳輸檔案的指令.傳回應該是150,否則出錯
setinf("開始傳輸檔案的指令伺服器響應的不是150,不知道伺服器是不是準備接受檔案!",150);
//讀取檔案///////////////////////
setinf("正在讀取檔案,準備傳輸...");
system.io.filestream fs;
byte[] fbins;
_pb.value=25;
fs=new system.io.filestream(filename,system.io.filemode.open,system.io.fileaccess.read);
fbins=new byte[fs.length] ;
fs.read(fbins,0,system.convert.toint32(fs.length));
catch( system.exception ex2)
setinf("檔案讀取失敗,失敗原因:"+ex2.message);
_pb.value=35;
/////////////////////////////////////////////////////
networkstream tmx=tcm.getstream();//獲得流
setinf("正在向網絡資料流中寫入資料...");
_pb.value=45;
tmx.write(fbins,0,fbins.length);//寫入資訊
tmx=null;
tcm.close();
_pb.value=55;
if (retok(getmsg(),"226")==false)//一般226資訊為兩次 ,本次是說明磁盤目前可用大小已經使用大小
string tmp3;
_pb.value=65;
tmp3=docommand("size "+ filename);//擷取大小.
setinf(tmp3);
_pb.value=75;
if (retok(tmp3,"213"))//傳回大小
setinf("正在核對檔案大小");
int ln=system.convert.toint32(tmp3.substring(4));//得到遠端檔案的大小
_pb.value=89;
if( ln==fbins.length)//如果大小相同.說明完整傳輸.
setinf("檔案傳輸成功!",0);
return true;
setinf("檔案傳輸後檔案大小不一緻!",213);
_pb.value=100;
setinf("檔案傳輸成功,但确認檔案大小時伺服器響應的不是213!是以無法保證資料傳輸是否正确!",213);
return false;
/// 從消息裡提取用于傳輸檔案的伺服器位址和端口
/// <param name="inf">消息</param>
/// <returns>數組,0為ip位址,1為端口.</returns>
private string[] getip(string inf)
string[] rt=new string[2];
if (inf.indexof("(")>0 )
string ips=inf.substring( inf.indexof("(")+1);
ips=ips.substring(0,ips.indexof(")"));
string[] ip=ips.split(",".tochararray());
rt[0]=ip[0]+"."+ip[1]+"."+ip[2]+"."+ip[3];//前面4組byte是ip位址.
int x1=system.convert.toint16(ip[4]);//ip位址
int x2=system.convert.toint16(ip[5]);//端口
int rtx=x1*256+x2;//計算端口.消息裡後兩組byte是端口,前者乘256加上後者就是伺服器給你的端口.
rt[1]=rtx.tostring();
return rt;
public bool downloadfile(string svrfilename,string savetofilename)
string filename=svrfilename;
docmd("noop","200");
_pb.value=25;
setinf("模式設定失敗!",200);
_pb.value=34;
_pb.value=40;;
_pb.value=50;
string inf=docommand("retr "+ filename);
if (inf.indexof("150")==-1)
setinf(inf);
_pb.value=60;
setinf("正在準備接收檔案...");
fs=new system.io.filestream(savetofilename,system.io.filemode.openorcreate ,system.io.fileaccess.readwrite );
setinf("檔案建立或打開失敗,失敗原因:"+ex2.message);
///
_pb.value=70;
setinf("正在接收檔案...");
int i=0;
int c=0;
do
byte[] dats=new byte[10240];
i=tmx.read(dats,0,dats.length);
c+=i;
system.windows.forms.application.doevents();
fs.write(dats,0,i);
this.infsshow.text=c+"位元組已複制.";
while (i>0 );
c=0;
this.infsshow.text="正在儲存檔案!";
fs.close();
this.infsshow.text="";
}