用C#实现HTTP协议下的多线程文件传输

2016-02-19 15:07 50 1 收藏

有了下面这个用C#实现HTTP协议下的多线程文件传输教程,不懂用C#实现HTTP协议下的多线程文件传输的也能装懂了,赶紧get起来装逼一下吧!

【 tulaoshi.com - 编程语言 】

  很多人都有过使用网络蚂蚁或网络快车软件下载互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间。这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载和断点续传技术。如果我们自己来编写一个类似这样的程序,也能够快速的在互联网上下载文件,那一定是非常愉快的事情。下面我就讲一讲如何利用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 ;//线程支持

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  增加如下的程序变量:

  

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;//接收文件的URL public 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 (nreadsize0)   {    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类中。下面定义开始接收按钮控件的事件响应函数:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  

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;ithread;i++) {  threadw[i]=false;//每个线程状态的初始值为假  filenamew[i]=i.ToString ()+".dat";//每个线程接收文件的临时文件名  if (ithread-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;jthread;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 ();}

来源:https://www.tulaoshi.com/n/20160219/1608923.html

延伸阅读
Timer类:设置一个定时器,定时执行用户指定的函数。 定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数。 初始化一个Timer对象: Timer timer = new Timer(timerDelegate, s,1000, 1000); // 第一个参数:指定了TimerCallback 委托,表示要执行的方法; // 第二个参数:一个包含回调方法要使用的信息的对象,或者为空引用;...
在TCP/IP网络结构中,为了保证网络安全,网络人员往往需要在路由器上添加防火墙,禁止非法用户用FTP等安全危害较大的TCP/IP协议访问主机。而有时系统维护人员需要用ftp将一些文件从中心机房主机传到前端网点主机上,比如应用程序的替换升级。假如每次传输文件时都要打开防火墙,未免显得有些繁琐,要是在自己的应用程序中增加一个专门的文件传输...
一.概述: 本文通过一个实例向大家介绍用Visual C#进行Internet通讯编程的一些基本知识。我们知道.Net类包含了请求/响应层、应用协议层、传输层等层次。在本程序中,我们运用了位于请求/响应层的WebRequest类以及WebClient类等来实现高抽象程度的Internet通讯服务。本程序的功能是完成网络文件的下载。 二.实现原理: 程...
TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程。然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实现不是一天两天的功夫,所幸的是在.net framework环境下,我们不必要去追究TCP协议底层的实现,一样可以很方便的编写出基于TCP协议进行网络通讯...
一.概述: 本文通过一个实例向大家介绍用C# Builder进行Internet通讯编程的一些基本知识。我们知道.Net类包含了请求/响应层、应用协议层、传输层等层次。在本程序中,我们运用了位于请求/响应层的WebRequest类以及WebClient类等来实现高抽象程度的Internet通讯服务。本程序的功能是完成文件的下载。 二.实现原理: 程序实...

经验教程

477

收藏

79
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部