您的位置:首页 > 编程语言 > C#

[原译]C#编写FTP客户端软件

2012-10-09 09:05 405 查看


1 介绍

我知道。网上有很多现成的FTP软件。但是。我们也想要了解FTP的一些底层机构,因此。 这个开源的项目在你学习FTP知识的时候也许对你有些帮组。程序的界面看起来像FileZilla,FileZilla虽然流行但是有些bug,当我打开我博客的时候总是有问题。我需要通过FTP连接我的服务器。发送文件,下载文件等等。因为。我决定写我自己的软件来处理所有的情况。FileZilla足够好。但它不是我的。

2 背景

看看我们已经知道的。我们知道FTP是一个标准的基于TCP网络协议。用于从一个主机向另一个主机传输文件。它是一个C/S架构。

图2



FTP程序曾经是基于命令行的。我们仍沿可以通过cmd.exe连接FTP服务器。因为FTP的确可以通过命令来操作。举个例子。我们可以在命令行使用“stor”命令来发送文件。为了完成这些请求。FTP服务器需要一直运行等待即将到来的客户端请求。我们可以从来自维基百科的解释更好的理解FTP:

客户端计算机可以通过服务器的21端口和服务器通信。叫做控制连接。它在一次会话期间保持开放。第一次连接的时候。叫做数据连接,服务器可以对客户端打开20端口(主动模式),建立一条数据通路,连接上客户端传输数据。或者客户端打开一个随机的端口(被动模式),去连接服务器,来传输数据。控制连接使用一个类似Telnet的协议,被用作客户端和服务器会话管理(命令,标识,密码)。。比如。"RETR filename" 会从服务器端下载文件。

图三



一个完整的FTP文件传输需要建立两种类型的连接,一种为文件传输下命令,称为控制连接,另一种实现真正的文件传输,称为数据连接。

服务器 通过三位ASCII的数字状态码,可能包含可选的描述信息,在控制连接上做出回应。比如。“200”或者是“200 OK”,表示上一条命令成功了。数字代表编号,描述信息给出了一些说明(比如“OK”),或者可能是一些需要的参数(比如需要帐号来存储文件),那么我们需要怎么做呢。很明显。发送命令,接收“OK”回应,发送数据。接收数据。完了。但是首先需要服务器已经准备好了。FTP服务器可以在主动和被动两种模式下运行。主动模式是基于服务器的连接而被动模式是基友客户端的连接。继续看。

在主动连接中,客户端把自己的ip和端口发送给服务器。然后服务器尝试连接到客户端,但是可能会因为防火墙的原因而被拒绝。我们在windows上都会使用反病毒/自带防火墙。是吧。那么我们来看看被动模式

在被动连接中。服务器通过一个“PASV”命令把自己的ip和端口发送给客户端。然后客户端通过该IP尝试连接服务器。对于发送文件非常有用。当我们发送文件的时候。优先使用“PASV”模式,如你们所说。大多数协议。像FTP/HTTP 使用ASCII编码,因为全球可用。因此我们会使用这种编码。你可以从下面得到FTP的命令列表

主动和被动都是对于服务器端来说的

3 使用代码

现在我们已经为编写软件做好准备了。我们写些有用的代码吧。:)首先。我们“打开文件对话框”,集成到我们的窗体里。

3.1 资源管理器组件

我们需要一个资源管理器组件在软件界面可以看到我们所有的文件。这样我们才可以选择哪些文件来发送到FTP服务器,新建一个Windows窗体控件库(下载包中提供了)

图四



最后看起来样子是上面这样。先添加一个TreeView,一些按钮,和一个搜索功能

TreeView.Nodes.Clear();

TreeNode nodeD = new TreeNode();

nodeD.Tag = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

nodeD.Text = "Desktop";

nodeD.ImageIndex = 10;

nodeD.SelectedImageIndex = 10;

TreeView.Nodes.Add(nodeD);


就像上面代码展示的那样。我们需要添加地一个主节点。我的文档。我的电脑等等。然后获得子目录。

string[] dirList;
dirList = Directory.GetDirectories(parentNode.Tag.ToString());
Array.Sort(dirList);
if (dirList.Length == parentNode.Nodes.Count)
return;
for (int i = 0; i < dirList.Length; i++)
{
node = new TreeNode();
node.Tag = dirList[i];
node.Text = dirList[i].Substring(dirList[i].LastIndexOf(@"\") + 1);
node.ImageIndex = 1;
parentNode.Nodes.Add(node);
}


可以从下载包里看到完整的代码。我们还应该处理鼠标单击事件。

现在我们有了一个资源管理器。还有FTP和VS所需要的所有信息。

首先,我们连接服务器。我们应该怎么做呢?

FTPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
AppendText(rchLog,"Status : Resolving IP Address\n",Color.Red);
remoteAddress = Dns.GetHostEntry(Server).AddressList[0];
AppendText(rchLog, "Status : IP Address Found ->" + remoteAddress.ToString() + "\n", Color.Red);
addrEndPoint = new IPEndPoint(remoteAddress, Port);
AppendText(rchLog,"Status : EndPoint Found ->" + addrEndPoint.ToString() + "\n", Color.Red);
FTPSocket.Connect(addrEndPoint);


是的。我们需要一个socket连接到服务器 ,然后发送命令


AppendText(rchLog, "Command : " + msg + "\n", Color.Blue);
Byte[] CommandBytes = Encoding.ASCII.GetBytes((msg + "\r\n").ToCharArray());
FTPSocket.Send(CommandBytes, CommandBytes.Length, 0);
//read Response
ReadResponse();


我们发送命令到服务器。服务器以他自己的语言来响应。我们需要理解他。响应包括3位数字和一些解释。

private string SplitResponse()
{
try
{
while (true)
{
Bytes = FTPSocket.Receive(Buffer, Buffer.Length, 0); //Number Of Bytes (Count)
StatusMessage += Encoding.ASCII.GetString(Buffer, 0, Bytes); //Convert to String
if (Bytes < Buffer.Length)  //End Of Response
break;
}
string[] msg = StatusMessage.Split('\n');
if (StatusMessage.Length > 2)
StatusMessage = msg[msg.Length - 2];  //Remove Last \n
else
StatusMessage = msg[0];
if (!StatusMessage.Substring(3, 1).Equals(" "))
return SplitResponse();
for (int i = 0; i < msg.Length - 1; i++)
AppendText(rchLog, "Response : " + msg[i] + "\n", Color.Green);
return StatusMessage;
}
catch(Exception ex)
{
AppendText(rchLog, "Status : ERROR. " +ex.Message+ "\n", Color.Red);
FTPSocket.Close();
return "";
}
}


完了。现在我们可以下载,上传,重命名。或者删除了。

4 FTP命令列表

命令描述
ABOR中断一个活动的文件传输
ACCT系统帐号信息
ADAT认证/安全数据
ALLO分配空间来接收文件
APPE添加文件到服务器
AUTH认证/安全机制
CCC清除命令通道
CDUP转到父目录
CONF机密性保护命令
CWD改变服务器上的工作目录
DELE删除服务器上的指定文件
ENC机密保护通道
EPRT指定一个服务器应该连接的扩展地址和端口
EPSV进入扩展的被动模式
FEAT得到服务器提供的功能列表
HELP返回指定命令信息
LANG返回语言信息
LIST如果是文件名列出文件信息,如果是目录则列出文件列表
LPRT指定一个服务器应该连接的长地址和端口
LPSV进入长被动模式
MDTM返回文件最近修改时间
MIC完整的保护命令
MKD创建目录
MLSD列出指定目录的内容
MLST在命令行上列出对象的精确信息
MODE传输模式(S=流模式,B=块模式,C=压缩模式)
NLST列出指定目录内容
NOOP无动作,(虚包,来自常连接中)
OPTS选择一个功能的选项
PASS验证密码
PASV进入被动模式
PBSZ保护缓冲区大小
PORT指定服务器应该连接的地址和端口
PROT数据通道保护级别
PWD显示当前工作目录
QUIT从FTP服务器上退出登录
REIN重新初始化登录状态连接
REST由指定点重启文件传递
RETR传递文件副本
RMD在服务器上删除指定目录
RNFR从旧名称重命名
RNTO到新名称
SITE向远程服务器发送指定命令
SIZE返回文件大小
SMNT挂载指定文件结构
STAT返回当前状态
STOR储存(复制)文件到服务器上
STOU储存文件到服务器指定文件上
STRU设置结构(F=文件,R=记录,P=页面)
SYST返回服务器使用的操作系统
TYPE传输模式(A=ASCII,E=EBCDIC,I=binary)
USER验证用户
XCUP跳到当前工作路径的父目录
XMKD新建目录
XPWD输出当前工作目录
XRMD删除目录

5 返回码列表

2xx –返回成功

4xx or 5xx – 返回失败

1xx or 3xx – 错误或不完整的回复

第二位定义了错误的类型

x0z – 语法 – 有语法错误.

x1z – 信息 – 请求提供信息

x2z – 连接 – 说明控制或数据连接有问题

x3z – 账户认证 – 登录或者是账户认证有问题.

x4z – 未定义

x5z – 文件系统 – 可能是服务器文件系统有问题。

Demo 下载

C#编写FTP客户端

6 许可

本文包括源代码和文件在CPOL下授权。

原文地址:File-Transfer-Protocol-FTP-Client

著作权声明:本文由http://leaver.me 翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: