1 / 29

C# 网络编程技术教程

C# 网络编程技术教程. 第七章 FTP 编程. 学习目标. 了解 FTP 的相关基础知识。 掌握 .NET 中 FTP 的服务器端编程方法。 掌握 .NET 中 FTP 的客户端编程方法。. 本章内容. 7.1 FTP 概述 7.2 .NET 中的 FTP 编程. 7.1 FTP 概述.

mervyn
Download Presentation

C# 网络编程技术教程

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C#网络编程技术教程 第七章 FTP编程

  2. 学习目标 • 了解FTP的相关基础知识。 • 掌握.NET中FTP的服务器端编程方法。 • 掌握.NET中FTP的客户端编程方法。

  3. 本章内容 7.1 FTP概述 7.2 .NET中的FTP编程

  4. 7.1 FTP概述 FTP(File Transfer Protocol,文件传输协议)是Internet中相当重要的应用之一。通过FTP,用户可从FTP服务器下载(Download)或上传(Upload)文件。FTP被整合在浏览器中,用户可利用浏览器通过超链接(Hyperlink),下载服务器开放的任意文件,达到资源共享的目的。 FTP是一种Client/Server体系结构,但与一般的Client/Server体系结构不同。与Socket网络程序应用的最大差别,在于其定义了服务器端与客户端的行为模式,即相关的指令、响应及传输的数据类型。因此在开发FTP应用程序时,应先了解FTP的详细内容。 FTP是由RFC959 File Transfer Protocol(FTP)所定义的。在此RFC中,强调了FTP的目的为:  文件共享。  通过应用程序直接或间接使用远程主机。  提供一致性的协议,避免用户在不同主机上产生不同的操作方式。  提供可靠及有效率的数据传输。

  5. 7.1 FTP概述 7.1.1 FTP结构 一般的Client/Server应用程序,只会在服务器端与客户端建立一个Socket连接,此连接同时处理服务器端与客户端间的连接以及数据的传输。而FTP则不同,服务器与客户端之间共建立两个Socket连接,一个以FTP默认端口21作为两者间的通信连接,另一个则用于客户端传输指令与服务器响应结果。FTP服务器端分为Protocol Interpreter(PI)及Data Transfer Process(DTP)两个模块。服务器端PI用来建立服务器Socket以监听并接收处理FTP客户端的连接请求,此连接会一直持续至客户端结束FTP应用程序为止。 FTP服务器端DTP专门处理FTP协议所定义的特殊指令,并将执行结果或信息返回至客户端。因此,DTP主要是负责传输数据(包括文件)。 FTP客户端分为Protocol Interpreter(PI)、Data Transfer Process(DTP)及User Interface(UI)三个模块。FTP客户端PI用来与服务器建立连接。FTP客户端DTP用来将用户输入的FTP指令传输至服务器端处理,并且接收服务器端的响应(包括文件的处理)。FTP客户端UI用来提供用户与PI间的交互界面。

  6. 7.1 FTP概述 7.1.2 FTP命令 除上述连接方式的特殊之外,FTP在命令与响应信息上也有其特殊的定义方式。FTP命令主要包括:访问命令、文件管理命令、数据格式命令、端口定义命令、文件传输命令和杂项命令。这些命令格式及描述分别见表7.1至表7.6所示。

  7. 7.1 FTP概述 7.1.2 FTP命令

  8. 7.1 FTP概述 7.1.2 FTP命令

  9. 7.1 FTP概述 7.1.2 FTP命令

  10. 7.1 FTP概述 7.1.3 FTP服务器响应码 RFC959对于FTP指令均明确定义其对应的FTP服务器响应信息,也称FTP服务器响应码,常用的FTP服务器响应码如表7.7所示。响应码由3位数字组成。其中第一位与第二位数字有其特殊的意义,分别如表7.8和表7.9所示。

  11. 7.1 FTP概述 7.1.3 FTP服务器响应码

  12. 7.1 FTP概述 7.1.3 FTP服务器响应码

  13. 7.1 FTP概述 7.1.3 FTP流程 FTP流程是指在FTP协议的基础上,客户端与服务器端完成一次完整的数据信息传输(文件下载或上传)的过程。FTP流程通常由以下三个部分构成。 (1)用户身份确认。 (2)数据传输。 (3)结束FTP。 下面以下载文件操作为例,详细说明上述三个部分的处理流程。 1.用户身份确认 如图7.2所示。首先,FTP客户端尝试与FTP服务器建立连接。命令格式如下。 C:\>ftp localhost 若成功,服务器发回响应成功信息。信息格式如下。 Connected to localhost. 220 FTP Server - <version 1.0> - ready. 同时服务器要求用户输入登录账号。格式如下。 User (localhost: (none)): 用户输入账号并按下Enter键后,客户端则传输“USER<username>”的信息至FTP服务器,此时服务器将再次发回响应信息,同时提示用户输入密码。格式如下: 331 Password required for<username> Password:

  14. 7.1 FTP概述 7.1.4 FTP流程 其中<username>为用户刚刚输入的账号。如:User (localhost: (none)):jh 331 Password required for jh Password: 用户输入密码并按下Enter键,客户端则传输“PASS<password>”信息至FTP服务器,并进行用户确认,若正确,服务器发回响应信息。格式如下。 230 User leo logged in. ftp> 至此,完成用户确认的流程。

  15. 7.1 FTP概述 7.1.4 FTP流程 2.数据传输 如图7.3所示,登录成功后,用户便可以输入相关的FTP指令至服务器。 例如要从FTP服务器下载文件download.txt。用户应在FTP提示符下输入下载命令,格式如下: ftp> download.txt 客户端首先会传输PORT h1,h2,h3,h4,p1,p2至服务器,以便以此IP地址及端口与服务器端建立DTP数据传输的连接;如果连接成功,服务器发回响应信息,格式如下: PORT 127,0,0,1,4,69 200 PORT command successful. 同时客户端会由DTP自动传输RETR download.txt指令至服务器,以便下载文件。当服务器端开始传输文件时,服务器会发回响应信息,格式如下: 150 Opening BINARY mode data connection for download.txt. 当下载成功后,服务器则发回如下信息: 226 Closing data connection. Transfer Complete. ftp: 15bytes received in 0.00Seconds 15000.00Kbytes/sec. 至此,数据传输结束。

  16. 7.1 FTP概述 7.1.4 FTP流程 3.结束FTP 流程如图7.4所示。当数据传输结束后,如不需要再进行其他文件传输,则FTP客户端发送QUIT命令,要求结束FTP连接。FTP服务器端则发回响应信息,表示结束连接。示例如下: ftp> quit 221 Server closing control connection. Goodbye. 图7.3数据传输流程 图7.4结束FTP流程

  17. 7.2 .NET中的FTP编程 文件传输系统服务器端和客户端的流程是:服务器端首先进行TCP监听,当有客户端连接请求时,将文件目录发送过去,客户端选择文件后,服务器构造一个文件流读取指定文件,然后将文件流赋给网络流发送到客户端,客户端接到网络流后,转化为文件流存放到文件。 7.2.1 数据发送和接收编程方法 1.数据发送编程方法 (1)当客户端输入了put命令后,会执行以下的代码向FTP服务器发送STOR命令,然后再通过sendData( )方法发送文件数据。如果接收成功,会收到226响应代码。要发送的文件数据通过readFileData( )方法读取。 (2)要发送的文件的数据通过readFileData( )方法获得,参数filename是要读取数据的文件名,返回值是从文件中读取的字节数据。 (3)获得文件数据后,通过sendData( )方法将其发送到FTP服务器。如果是PASV模式,就直接连接FTP服务器,然后发送数据;如果是PORT模式,就等待dataSocket为连接状态时发送。 2.数据接收编程方法 (1)当客户端输入了get命令后,会执行以下的代码从FTP服务器接收文件。如果接收成功,会收到了226响应代码,否则可能会收到550响应代码。接收文件数据通过receiveData( )函数完成,如果接收数据正确,返回值为文件内容,否则返回空字符串。如果接收到文件数据,就调用saveFileData( )方法进行保存。 (2)接收到文件数据后,通过saveFileData( )方法把数据写入文件中:参数filename是要保存的文件名,参数data是要写入的数据。代码首先检查文件是否存在,如果不存在就创建一个新文件。

  18. 7.2 .NET中的FTP编程 7.2.2 服务器端开发 1.界面设计 如图7.5所示,在窗体上拖放3个Label控件、1个TextBox控件、3个Button控件、2个RichTextBox控件、1个StatusBar控件。设置各个控件的属性如表7.10所示。

  19. 7.2 .NET中的FTP编程 7.2.2 服务器端开发 2.在代码窗口中添加引用 using System.Net; using System.Net.Sockets; using System.Threading; using System.IO; 3.在代码窗口中添加私有成员 private bool control=false; private int port; private System.Net.Sockets.Socket sock; private int number; private int i; private int j; private System.Net.Sockets.TcpListener listener; private System.Windows.Forms.StatusBarPanel statusBarPanel1; private System.IO.FileStream filestream; 4.修改Form1构造方法 在Form1窗口中,单击鼠标右键选择“查看代码”,进入代码窗口。 public Form1( ) { // Windows 窗体设计器支持所必需的 InitializeComponent( ); // // TODO: 在 InitializeComponent 调用后添加任何构造函数代码 string[ ] str=new string[1024]; for(int i=0;i<Directory.GetFiles("d:\\FTP虚拟目录").Length;i++) { str[i]=Directory.GetFiles("d:\\FTP虚拟目录")[i]; richTextBox1.AppendText(str[i]+"\r\n"); } } 图7.5服务器端窗口

  20. 7.2 .NET中的FTP编程 7.2.2 服务器端开发 5.“开始服务”按钮的Click事件代码 private void button1_Click(object sender, System.EventArgs e) { try { port=Int32.Parse(textBox1.Text); } catch{MessageBox.Show("您输入的格式不对!请输入正整数。");} try { listener=new TcpListener(port); listener.Start( ); statusBarPanel1.Text="开始监听………"; Thread thread =new Thread(new ThreadStart(receive)); thread.Start( ); } catch(Exception ex){MessageBox.Show(ex.Message);} } 6.Receive( )方法代码 private void receive( ) { sock=listener.AcceptSocket( ); if(sock.Connected) { statusBarPanel1.Text="与客户建立连接"; string str=richTextBox1.Text; byte[] bytee=System.Text.Encoding.BigEndianUnicode.GetBytes(str.ToChar Array( )); sock.Send(bytee,bytee.Length,0);

  21. 7.2 .NET中的FTP编程 7.2.2 服务器端开发 //接收信息 while(!control) { NetworkStream stream=new NetworkStream(sock); byte[ ] by=new Byte[1024]; int i=sock.Receive(by,by.Length,0); string ss=System.Text.Encoding.BigEndianUnicode.GetString(by); richTextBox2.AppendText(ss); j=richTextBox2.Lines.Length; if(j>=2) { if(richTextBox2.Lines[j-2].ToString( )!="@@@@@@") {//构造文件流 filestream=new FileStream(richTextBox2.Lines[j-2].ToString( ),FileMode.Open,FileAccess.Read); //定义缓冲区 byte[] b1=new byte[1024]; //循环读文件 while((number=filestream.Read(b1,0,1024))!=0) {//向客户端发送流 stream.Write(b1,0,number); //流刷新 stream.Flush( ); } //文件发送结束,发送"<EOF>",提示客户文件传输完毕。 string st="<EOF>"; byte[] b2=new byte[1024]; byt=System.Text.Encoding.ASCII.GetBytes(st.ToCharArray( )); sock.Send(b2,b2.Length,0); filestream.Close( ); }

  22. 7.2 .NET中的FTP编程 7.2.2 服务器端开发 else if(richTextBox2.Lines[j-2].ToString( )=="@@@@@@") { control=true; } } } } } 7.“关闭服务”按钮的Click事件代码 private void button2_Click(object sender, System.EventArgs e) { try { control=true; listener.Stop( ); statusBarPanel1.Text="停止监听"; } catch{MessageBox.Show("监听还未开始,关闭无效。");} } 8.“退出服务”按钮的Click事件代码 private void button3_Click(object sender, System.EventArgs e) { Application.Exit( ); }

  23. 7.2 .NET中的FTP编程 7.2.3 客户端开发 1.界面设计 如图7.6所示,在窗体上拖放5个Label控件、3个TextBox控件、3个Button控件、1个GroupBox控件、1个RichTextBox控件、1个StatusBar控件、1个ComboBox控件、1个saveFileDialog控件。设置各个控件的属性如表7.11所示。

  24. 7.2 .NET中的FTP编程 7.2.3 客户端开发 2.在代码窗口中添加引用 图7.6 客户端窗口 using System.Net; using System.Net.Sockets; using System.IO; using System.Threadingt; 3.在代码窗口中添加私有成员 private bool control=false; private TcpClient client; private int i; private NetworkStream netStream; private FileStream fileStream=null; private Stream stream=null; 图7.6客户端窗口

  25. 7.2 .NET中的FTP编程 7.2.3 客户端开发 4.“连接”按钮的Click事件代码 private void button1_Click(object sender, System.EventArgs e) { int port=0; IPAddress myIP=IPAddress.Parse("127.0.0.1"); try { myIP=IPAddress.Parse(textBox3.Text); } catch{MessageBox.Show("您输入的IP地址格式错误!");} client=new TcpClient( ); try { port=Int32.Parse(textBox2.Text); } catch{MessageBox.Show("请输入整数。");} try { if(textBox1.Text!=" "&&textBox3.Text==" ") { client.Connect(textBox1.Text,port); statusBarPanel1.Text="与服务器建立连接"; //获取网络流 netStream=client.GetStream( ); //读数据 byte[] b=new byte[6400]; i=netStream.Read(b,0,6400); string str=System.Text.Encoding.BigEndianUnicode.GetString(b);

  26. 7.2 .NET中的FTP编程 7.2.3 客户端开发 richTextBox1.AppendText(str); int j=richTextBox1.Lines.Length; for(int k=0;k<j-1;k++) { comboBox1.Items.Add(richTextBox1.Lines[k]); } comboBox1.Text=comboBox1.Items[0].ToString( ); } if(textBox3.Text!=""&&textBox1.Text=="") { client.Connect(myIP,port); statusBarPanel1.Text="与服务器建立连接"; netStream=client.GetStream( ); byte[] b=new byte[6400]; int i=netStream.Read(b,0,6400); string str=System.Text.Encoding.BigEndianUnicode.GetString(b); richTextBox1.AppendText(str); int j=richTextBox1.Lines.Length; for(int k=0;k<j-1;k++) { comboBox1.Items.Add(richTextBox1.Lines[k]); } comboBox1.Text=comboBox1.Items[0].ToString( ); }

  27. 7.2 .NET中的FTP编程 7.2.3 客户端开发 if(textBox3.Text!=""&&textBox1.Text!="") { client.Connect(myIP,port); statusBarPanel1.Text="与服务器建立连接"; netStream=client.GetStream( ); byte[] b=new byte[6400]; int i=netStream.Read(b,0,6400); string str=System.Text.Encoding.BigEndianUnicode.GetString(b); richTextBox1.AppendText(str); int j=richTextBox1.Lines.Length; for(int k=0;k<j-1;k++) { comboBox1.Items.Add(richTextBox1.Lines[k]); } comboBox1.Text=comboBox1.Items[0].ToString( ); } } catch(Exception ex){MessageBox.Show(ex.Message);} } 5.“下载”按钮的Click事件代码 private void button2_Click(object sender, System.EventArgs e) { control=false; if(saveFileDialog1.ShowDialog( )==DialogResult.OK) { //创建新的文件流 filestream=new FileStream(saveFileDialog1.FileName,FileMode.OpenOrCreate,FileAccess.Write); //获取服务器网络流 netStream=client.GetStream( ); string down=comboBox1.Text+"\r\n"; byte[] b=System.Text.Encoding.BigEndianUnicode.GetBytes(down.ToCharArray( ));

  28. 7.2 .NET中的FTP编程 7.2.3 客户端开发 //发送要下载的文件名给服务器 netStream.Write(b,0,b.Length); //流刷新 netStream.Flush( ); //启动接收文件的线程 Thread thread=new Thread(new ThreadStart(download)); thread.Start( ); } } 6.Download( )方法的定义 //此方法用于接收服务器传来的流(要下载的文件) private void download( ) { Stream stream=null; //获取网络流 stream=client.GetStream( ); int length=1024; byte[] b=new byte[1024]; int num=stream.Read(b,0,length); //读取网络流并写入文件 while(num>0) { //读取服务器流 string str=System.Text.Encoding.ASCII.GetString(b); int m=str.IndexOf("<EOF>"); if(m==-1) { filestream.Write(b,0,num); filestream.Flush( ); statusBarPanel1.Text="正在下载文件"; }

  29. 7.2 .NET中的FTP编程 7.2.3 客户端开发 else { filestream.Write(b,0,m); filestream.Flush( ); break; } } filestream.Close( ); MessageBox.Show("下载完毕!"); statusBarPanel1.Text="文件下载完毕"; } 7.“关闭”按钮的Click事件代码 private void button3_Click(object sender, System.EventArgs e) { try { netStream=client.GetStream( ); string end="@@@@@@"+"\r\n"; byte[] byt=System.Text.Encoding.BigEndianUnicode.GetBytes(end.ToCharArray( )); netStream.Write(byt,0,byt.Length); netStream.Flush( ); client.Close( ); statusBarPanel1.Text="与服务器断开连接"; } catch{} }

More Related