作者:董海林

下载源代码

  很多人都有过使用网络蚂蚁或网络快车软件下载互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间。这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载和断点续传技术。如果我们自己来编写一个类似这样的程序,也能够快速的在互联网上下载文件,那一定是非常愉快的事情。下面我就讲一讲如何利用C#语言编写一个支持多线程下载文件的程序,你会看到利用C#语言编写网络应程序是多么的容易,从中也能体会到C#语言中强大的网络功能。
  首先介绍一下HTTP协议,HTTP亦即Hpyer Text Transfer Protocal的缩写,它是现代互联网上最重要的一种网络协议,超文本传输协议位于TCP/IP协议的应用层,是一个面向无连接、简单、快速的C/S结构的协议。HTTP的工作过程大体上分连接、请求、响应和断开连接四个步骤。C#语言对HTTP协议提供了良好的支持,在.NET类库中提供了WebRequest和WebResponse类,这两个类都包含在System.Net命名空间中,利用这两个类可以实现很多高级的网络功能,本文中多线程文件下载就是利用这两个类实现的。 WebRequest和WebResponse都是抽象基类,因此在程序中不能直接作为对象使用,必须被继承,实际使用中,可根据URI参数中的URI前缀选用它们合适的子类,对于HTTP这类URI,HttpWebRequest和HttpWebResponse类可以用于处理客户程序同WEB服务器之间的HTTP通讯。
  HttpWebRequest类实现了很多通过HTTP访问WEB服务器上文件的高级功能。HttpWebRequest类对WebRequest中定义的属性和方法提供支持,HttpWebRequest将发送到Internet资源的公共HTTP标头的值公开为属性,由方法或系统设置,常用的由属性或方法设置的HTTP标头为:接受, 由Accept属性设置, 连接, 由Connection属性和KeepAlive属性设置, Content-Length, 由ContentLength属性设置, Content-Type, 由ContentType属性设置, 范围, 由AddRange方法设置. 实际使用中是将标头信息正确设置后,传递到WEB服务器,WEB服务器根据要求作出回应。
  HttpWebResponse类继承自WebResponse类,专门处理从WEB服务器返回的HTTP响应,这个类实现了很多方法,具有很多属性,可以全面处理接收到的互联网信息。在HttpWebResponse类中,对于大多数通用的HTTP标头字段,都有独立的属性与其对应,程序员可以通过这些属性方便的访问位于HTTP接收报文标头字段中的信息,本例中用到的HttpWebResponse类属性为:ContentLength 既接收内容的长度。
  有了以上的了解后,下面看看这两个类的用法,要创建HttpWebRequest对象,不要直接使用HttpWebRequest的构造函数,而要使用WebRequest.Create方法初始化一个HttpWebRequest实例,如:

HttpWebRequest hwr=(HttpWebRequest)WebRequest.Create(http://www.163.com/); 

创建了这个对象后,就可以通过HttpWebRequest属性,设置很多HTTP标头字段的内容,如hwr.AddRange(100,1000);设置接收对象的范围为100-1000字节。
  HttpWebReques对象使用GetResponse()方法时,会返回一个HttpWebResponse对象,为提出HTTP返回报文信息,需要使用HttpWebResponse的GetResponseStream()方法,该方法返回一个Stream对象,可以读取HTTP返回的报文,如:首先定义一个Strean 对象 public System.IO.Stream ns; 然后 ns=hwr.GetResponse ().GetResponseStream ();即可创建Stream对象。 有了以上的准备知识后下面开始设计我们的多线程互联网文件的下载程序,首先打开Visual Studio.Net集成开发环境,选择“文件”、“新建”、“项目”,然后选择“Visual C#项目”,在向导右边列表框中选中“Windows 应用程序”,输入项目名称,如本例为:httpftp,然后选择“确定”按钮,向导自动生成了一个Windows应用程序项目。首先打开窗口设计器设计应用程序窗口,增加如下控件:
  一个列表框 listBox1 三个文本标签 label1-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 System.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.Threading ;//线程支持      

增加如下的程序变量:

public bool[] threadw; //每个线程结束标志public string[] filenamew;//每个线程接收文件的文件名public int[] filestartw;//每个线程接收文件的起始位置public int[] filesizew;//每个线程接收文件的大小public string strurl;//接受文件的URLpublic bool hb;//文件合并标志public int thread;//进程数      

定义一个HttpFile类,用于管理接收线程,其代码如下:

public class HttpFile{public Form1 formm;public 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.Dispose ();}public void receive()//接收线程{filename=formm.filenamew[threadh];strUrl=formm.strurl;ns=null;nbytes= new byte[512];nreadsize=0;formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"开始接收");fs=new FileStream (filename,System.IO.FileMode.Create);try{request=(HttpWebRequest)HttpWebRequest.Create (strUrl);//接收的起始位置及接收的长度request.AddRange(formm.filestartw [threadh],formm.filestartw [threadh]+formm.filesizew [threadh]);ns=request.GetResponse ().GetResponseStream ();//获得接收流nreadsize=ns.Read (nbytes,0,512);while (nreadsize>0){fs.Write (nbytes,0,nreadsize);nreadsize=ns.Read (nbytes,0,512);formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"正在接收");}fs.Close();ns.Close ();}catch (Exception er){MessageBox.Show (er.Message );fs.Close();}formm.listBox1 .Items.Add ("进程"+threadh.ToString ()+"接收完毕!");formm.threadw[threadh]=true;}}

该类和Form1类处于统一命名空间,但不包含在Form1类中。下面定义“开始接收”按钮控件的事件响应函数:

private void button1_Click(object sender, System.EventArgs e){DateTime dt=DateTime.Now;//开始接收时间textBox1.Text =dt.ToString ();strurl=textBox2.Text .Trim ().ToString ();HttpWebRequest request;long filesize=0;try{request=(HttpWebRequest)HttpWebRequest.Create (strurl);filesize=request.GetResponse ().ContentLength;//取得目标文件的长度request.Abort ();}catch (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 int[thread];//计算每个线程应该接收文件的大小int filethread=(int)filesize/thread;//平均分配int filethreade=filethread+(int)filesize%thread;//剩余部分由最后一个线程完成//为数组赋值for (int i=0;i<thread;i++){threadw[i]=false;//每个线程状态的初始值为假filenamew[i]=i.ToString ()+".dat";//每个线程接收文件的临时文件名if (i<thread-1){      filestartw[i]=filethread*i;//每个线程接收文件的起始点      filesizew[i]=filethread-1;//每个线程接收文件的长度}else{filestartw[i]=filethread*i;filesizew[i]=filethreade-1;}}//定义线程数组,启动接收线程Thread[] threadk=new Thread [thread];HttpFile[] httpfile=new HttpFile [thread];for (int j=0;j<thread;j++){httpfile[j]=new HttpFile(this,j);threadk[j]=new Thread(new ThreadStart (httpfile[j].receive ));threadk[j].Start ();}//启动合并各线程接收的文件线程Thread hbth=new Thread (new ThreadStart (hbfile));hbth.Start ();}

合并文件的线程hbfile定义在Form1类中,定义如下:

public void hbfile(){while (true)//等待{hb=true;for (int i=0;i<thread;i++){if (threadw[i]==false)//有未结束线程,等待{hb=false;Thread.Sleep (100);break;}}if (hb==true)//所有线程均已结束,停止等待,{break;}}FileStream fs;//开始合并FileStream fstemp;int readfile;byte[] bytes=new byte[512];fs=new FileStream (textBox3.Text .Trim ().ToString (),System.IO.FileMode.Create);for (int k=0;k<thread;k++){fstemp=new FileStream (filenamew[k],System.IO.FileMode .Open);while (true){readfile=fstemp.Read (bytes,0,512);if (readfile>0){fs.Write (bytes,0,readfile);}else{break;}}fstemp.Close ();}fs.Close ();DateTime dt=DateTime.Now;textBox1.Text =dt.ToString ();//结束时间MessageBox.Show ("接收完毕!!!");}

至此,一个多线程下载文件的程序就大功告成了,注意在输入本地文件名时,应按如下格式输入:

“c:\\test\\httpftp\\bin\\d.htm”,

因”\”后的字符在C#中是转义字符,线程数并非越大越好,一般5个线程就可以了,该程序在Visual Studio.Net 2002开发环境及Windows xp 操作系统上通过。

转载于:https://www.cnblogs.com/Googler/archive/2010/08/19/1803804.html

用C#语言实现http协议下的多线程文件传输相关推荐

  1. 【ASP.net文档】用C#实现HTTP协议下的多线程文件传输

    很多人都有过使用网络蚂蚁或网络快车软件下载互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间.这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载 ...

  2. 易语言客户端请求http_易语言通过Http协议上传下载文件

    易语言通过Http协议上传下载文件 2018-11-29 .版本 2 .程序集 窗口程序集1 .程序集变量 程序集_数据, 字节集 .子程序 _按钮1_被单击 信息框 (客户1.连接 ("b ...

  3. Linux下几种文件传输命令 sz rz sftp scp

    vbs自动启动程序 64位系统编译的程序,在32位系统中运行会有问题 Linux下几种文件传输命令 sz rz sftp scp 2011-10-28 16:08:47|  分类: 默认分类 |  标 ...

  4. linux系统中加密文件传输助手,Linux 下的安卓文件传输助手!

    如果你尝试在 Ubuntu 下连接你的安卓手机,你也许可以试试 Linux 下的安卓文件传输助手.本质上来说,这个应用是谷歌 macOS 版本的一个克隆.它是用 Qt 编写的,用户界面非常简洁,使得你 ...

  5. linux手机 电脑传文件怎么安装,如何在 Linux 下安装安卓文件传输助手

    如果你尝试在 Ubuntu 下连接你的安卓手机,你也许可以试试 Linux 下的安卓文件传输助手. 本质上来说,这个应用是谷歌 macOS 版本的一个克隆.它是用 Qt 编写的,用户界面非常简洁,使得 ...

  6. 安卓传输文件Linux,你知道Linux下的安卓文件传输助手的作用?

    如果你尝试在 Ubuntu 下连接你的安卓手机,你也许可以试试 Linux 下的安卓文件传输助手.本质上来说,这个应用是谷歌 macOS 版本的一个克隆.它是用 Qt 编写的,用户界面非常简洁,使得你 ...

  7. 安卓手机的文件如何传到linux里去,如何在Linux下安装安卓文件传输助手

    CTO练习营 | 12月3-5日,深圳,是时刻成为优良的技巧治理者了 如不雅你测验测验在 Ubuntu 下连接你的安卓手机,你也许可以尝尝 Linux 下的安卓文件传输助手. 如今,有可能一部分人想知 ...

  8. 科普|不同协议下远程服务器文件上传_下载优劣对比

    作为一个程序员,如果不知道如何进行远程服务器的文件上传与下载,实在是一件尴尬的事情.打开百度,搜索「远程服务器 上传下载」,你能得到 63,100,000 个搜搜结果,五花八门的操作方式的让人眼花缭乱 ...

  9. C#实现HTTP协议:多线程文件传输

    很多人都有过使用网络蚂蚁或网络快车互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间.这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载和断点续 ...

  10. c 语言 验证码识别算法,一个简单的文件传输验证码识别c/s实现

    一个简单的文件传输验证码识别c/s实现 大体思路 client通过tcp向server传输一个待识别的验证图片,server端识别后通过tcp回传给client. server端识别验证码采用pyte ...

最新文章

  1. CentOS学习笔记--程序管理
  2. java flux api,SpringBoot学习系列-WebFlux REST API 全局异常处理
  3. ZEN CART 在LINUX系统下设置邮箱方法---用GMAIL设置,方法选择SMTPAUTH
  4. oracle 换字段顺序,修改ORACLE的字段顺序
  5. MVVM是什么?谈谈你对MVVM的理解?
  6. all方法 手写promise_我团队的一年前端实现Promise所有方法
  7. 一次sendmsg的改造过程
  8. oracle国家字符集
  9. gif透明背景动画_汉服美女表情包(PS做GIF动图简易教程分享)
  10. CentOS操作系统密码复杂度策略设置
  11. WPS 国际版 Remove ads
  12. Javac源码简单分析之解析和填充符号表
  13. java根据业务排序利用Comparator.comparing自定义排序规则
  14. 有哪些高质量的英文有声书 audiobook?
  15. QT 5.15 最新安装指南(针对不同系统)
  16. Unix编程常见问题解答
  17. Java将查询到的List,list集合还嵌套一个list集合(把这个list集合和嵌套的list集合合并为一个list集合)
  18. 集合的基本概念和区别
  19. Centos 7安装步骤
  20. 单词接龙java实现

热门文章

  1. PHP trim()的使用
  2. 给JDK设置tmp目录的办法
  3. JAVA使用反射的方法,参数是数组怎么办?
  4. 编码基本功:给刚刚学习编程的朋友的建议
  5. 在NVME SSD上安装WIN7
  6. Dex Loader] Failed to load D:\adt-bundle-windows-x86_64-20190307\sdk\build-tools\28.0.3\lib\dx.jar
  7. 南宁公交有两个应用付费通道,互不通用
  8. 解决办法:string in namespace std does not name a type
  9. 苹果提交版本后显示”缺少出口合规证明“的解决办法
  10. eclipse缺少org.apache.http.legacy的解决办法