1、用 C#实现 HTTP 协议下的多线程文件传输本文关键词:HTTPC#编程.net很多人都有过使用网络蚂蚁或网络快车软件下载互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间。这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载和断点续传技术。如果我们自己来编写一个类似这样的程序,也能够快速的在互联网上下载文件,那一定是非常愉快的事情。下面我就讲一讲如何利用 C#语言编写一个支持多线程下载文件的程序,你会看到利用 C#语言编写网络应程序是多么的容易,从中也能体会到 C#语言中强大的网络功能。首先介绍一下 HTTP 协议,HTTP 亦即 Hp
2、yer Text Transfer Protocal 的缩写,它是现代互联网上最重要的一种网络协议,超文本传输协议位于 TCP/IP 协议的应用层,是一个面向无连接、简单、快速的 C/S 结构的协议。HTTP 的工作过程大体上分连接、请求、响应和断开连接四个步骤。C# 语言对 HTTP 协议提供了良好的支持,在.NET 类库中提供了WebRequest 和 WebResponse 类,这两个类都包含在 System.Net 命名空间中,利用这两个类可以实现很多高级的网络功能,本文中多线程文件下载就是利用这两个类实现的。 WebRequest 和 WebResponse 都是抽象基类,因此在程序
3、中不能直接作为对象使用,必须被继承,实际使用中,可根据 URI 参数中的 URI 前缀选用它们合适的子类,对于 HTTP 这类URI,HttpWebRequest 和 HttpWebResponse 类可以用于处理客户程序同 WEB 服务器之间的 HTTP 通讯。HttpWebRequest 类实现了很多通过 HTTP 访问 WEB 服务器上文件的高级功能。HttpWebRequest 类对 WebRequest 中定义的属性和方法提供支持,HttpWebRequest 将发送到 Internet 资源的公共 HTTP 标头的值公开为属性,由方法或系统设置,常用的由属性或方法设置的 HTTP
4、标头为:接受, 由 Accept 属性设置, 连接, 由 Connection 属性和KeepAlive 属性设置, Content-Length, 由 ContentLength 属性设置, Content-Type, 由ContentType 属性设置, 范围, 由 AddRange 方法设置. 实际使用中是将标头信息正确设置后,传递到 WEB 服务器,WEB 服务器根据要求作出回应。HttpWebResponse 类继承自 WebResponse 类,专门处理从 WEB 服务器返回的HTTP 响应, 这个类实现了很多方法,具有很多属性,可以全面处理接收到的互联网信息。在HttpWebRe
5、sponse 类中,对于大多数通用的 HTTP 标头字段,都有独立的属性与其对应,程序员可以通过这些属性方便的访问位于 HTTP 接收报文标头字段中的信息,本例中用到的HttpWebResponse 类属性为: ContentLength 既接收内容的长度。有了以上的了解后,下面看看这两个类的用法,要创建 HttpWebRequest 对象,不要直接使用 HttpWebRequest 的构造函数,而要使用 WebRequest.Create 方法初始化一个HttpWebRequest 实例,如:HttpWebRequest hwr=(HttpWebRequest)WebRequest.Crea
6、te(http:/ 创建了这个对象后,就可以通过 HttpWebRequest 属性,设置很多 HTTP 标头字段的内容,如 hwr.AddRange(100,1000);设置接收对象的范围为 100-1000 字节。HttpWebReques 对象使用 GetResponse()方法时,会返回一个 HttpWebResponse对象,为提出 HTTP 返回报文信息,需要使用 HttpWebResponse 的GetResponseStream()方法,该方法返回一个 Stream 对象,可以读取 HTTP 返回的报文,如:首先定义一个 Strean 对象public System.IO.St
7、ream ns; 然后ns=hwr.GetResponse ().GetResponseStream ();即可创建 Stream 对象。-有了以上的准备知识后下面开始设计我们的多线程互联网文件的下载程序,首先打开 Visual Studio.Net 集成开发环境,选择 “文件”、“新建”、“项目”,然后选择“Visual C#项目”,在向导右边列表框中选中“Windows 应用程序”,输入项目名称,如本例为:httpftp,然后选择“确定”按钮,向导自动生成了一个 Windows 应用程序项目。首先打开窗口设计器设计应用程序窗口,增加如下控件:一个列表框 listBox1 三个文本标签 la
8、bel1-label3 三个文本框 textBox1-textBox3 一个开始接收按钮 button1 设计好的窗口如下图:控件定义代码是:public System.Windows.Forms.ListBox listBox1;private System.Windows.Forms.Label label1;private System.Windows.Forms.TextBox textBox1private System.Windows.Forms.Button button1;private System.Windows.Forms.Label label2;private Sys
9、tem.Windows.Forms.TextBox textBox2;private System.Windows.Forms.Label label3;private System.Windows.Forms.TextBox textBox3;private System.Windows.Forms.Label label4;private System.Windows.Forms.TextBox textBox4;打开 Form1 的代码编辑器,增加如下的命名空间:using System.Net;/网络功能using System.IO;/流支持using System.Threadin
10、g ;/线程支持增加如下的程序变量:public bool threadw; /每个线程结束标志public string filenamew;/每个线程接收文件的文件名public int filestartw;/每个线程接收文件的起始位置public int filesizew;/每个线程接收文件的大小public string strurl;/接受文件的 URLpublic bool hb;/文件合并标志public int thread;/进程数定义一个 HttpFile类,用于管理接收线程,其代码如下:public class HttpFilepublic Form1 formm;p
11、ublic int threadh;/线程代号public string filename;/文件名public string strUrl;/接收文件的 URLpublic FileStream fs;public HttpWebRequest request;public System.IO.Stream ns;public byte nbytes;/接收缓冲区public int nreadsize;/接收字节数public HttpFile(Form1 form,int thread)/构造方法formm=form;threadh=thread;HttpFile()/析构方法formm
12、.Dispose ();public void receive()/接收线程filename=formm.filenamewthreadh;strUrl=formm.strurl;ns=null;nbytes= new byte512;nreadsize=0;formm.listBox1 .Items .Add (“线程“+threadh.ToString ()+“开始接收“);fs=new FileStream (filename,System.IO.FileMode.Create);tryrequest=(HttpWebRequest)HttpWebRequest.Create (strU
13、rl);/接收的起始位置及接收的长度request.AddRange(formm.filestartw threadh,formm.filestartw threadh+formm.filesizew threadh);ns=request.GetResponse ().GetResponseStream ();/获得接收流nreadsize=ns.Read (nbytes,0,512);while (nreadsize0)fs.Write (nbytes,0,nreadsize);nreadsize=ns.Read (nbytes,0,512);formm.listBox1 .Items .
14、Add (“线程“+threadh.ToString ()+“正在接收“);fs.Close();ns.Close ();catch (Exception er)MessageBox.Show (er.Message );fs.Close();formm.listBox1 .Items.Add (“进程“+threadh.ToString ()+“接收完毕!“);formm.threadwthreadh=true;该类和 Form1类处于统一命名空间,但不包含在 Form1类中。下面定义“开始接收”按钮控件的事件响应函数:private void button1_Click(object se
15、nder, System.EventArgs e)DateTime dt=DateTime.Now;/开始接收时间textBox1.Text =dt.ToString ();strurl=textBox2.Text .Trim ().ToString ();HttpWebRequest request;long filesize=0;tryrequest=(HttpWebRequest)HttpWebRequest.Create (strurl);filesize=request.GetResponse ().ContentLength;/取得目标文件的长度request.Abort ();c
16、atch (Exception er)MessageBox.Show (er.Message );/ 接收线程数thread=Convert.ToInt32 (textBox4.Text .Trim().ToString (),10);/根据线程数初始化数组threadw=new bool thread;filenamew=new string thread;filestartw=new int thread;filesizew=new intthread;/计算每个线程应该接收文件的大小int filethread=(int)filesize/thread;/平均分配int filethre
17、ade=filethread+(int)filesize%thread;/剩余部分由最后一个线程完成/为数组赋值for (int i=0;i0)fs.Write (bytes,0,readfile);elsebreak;fstemp.Close ();fs.Close ();DateTime dt=DateTime.Now;textBox1.Text =dt.ToString ();/结束时间MessageBox.Show (“接收完毕!“); 至此,一个多线程下载文件的程序就大功告成了,注意在输入本地文件名时,应按如下格式输入:“c:testhttpftpbind.htm”,因”后的字符在 C#中是转义字符,线程数并非越大越好,一般 5个线程就可以了,该程序在 Visual Studio.Net 2002开发环境及 Windows xp 操作系统上通过。内容均来自网上,自行遵守版权等作者权利