http协议多线程文件传输

摘要:
C#语言为HTTP协议提供了良好的支持。中提供WebRequest和WebResponse类。NET类库,两者都包含在System NET命名空间中,您可以使用这两个类来实现许多高级网络功能。在本文中,使用这两个类实现了多线程文件下载。HttpWebRequest类实现了许多通过HTTP访问Web服务器上文件的高级功能。HttpWebResponse类继承自WebResponse类,专门处理从Web服务器返回的HTTP响应。这个类实现了许多方法,具有许多属性,可以全面处理接收到的互联网信息。

      HTTP亦即Hpyer Text Transfer Protocal的缩写,它是现代互联网上最重要的一种网络协议,超文本传输协议位于TCP/IP协议的应用层,是一个面向无连接、简单、快速的C/S结构的协议。HTTP的工作过程大体上分连接、请求、响应和断开连接四个步骤。C#语言对HTTP协议提供了良好的支持,在.NET类库中提供了WebRequestWebResponse类,这两个类都包含在System.Net命名空间中,利用这两个类可以实现很多高级的网络功能,本文中多线程文件下载就是利用这两个类实现的。 WebRequestWebResponse都是抽象基类,因此在程序中不能直接作为对象使用,必须被继承,实际使用中,可根据URI参数中的URI前缀选用它们合适的子类,对于HTTP这类URI,HttpWebRequestHttpWebResponse类可以用于处理客户程序同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返回报文信息,需要使用HttpWebResponseGetResponseStream()方法,该方法返回一个Stream对象,可以读取HTTP返回的报文,

如:

首先定义一个Strean 对象

public System.IO.Stream ns;

然后

ns=hwr.GetResponse ().GetResponseStream ();即可创建Stream对象。

http协议多线程文件传输第1张http协议多线程文件传输第2张代码
using System.Net;//网络功能
using System.IO;//流支持
using System.Threading ;//线程支持
  

增加如下的程序变量:

public bool[] threadw; //每个线程结束标志
public string[] filenamew;//每个线程接收文件的文件名
public int[] filestartw;//每个线程接收文件的起始位置
public int[] filesizew;//每个线程接收文件的大小
public string strurl;//接受文件的URL
public 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 (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 ("接收完毕!!!");
}

免责声明:文章转载自《http协议多线程文件传输》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Asp.Net 高性能框架 SqlSugar.ORM 2.3linux中apt-get使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

初识安卓之利用Handler进行线程间数据传递

背景:点击界面上一个按钮,使文本框中的数字加1,此过程中,如果按钮点击事件是开启了一个新的线程,让文本框中的文字加1,则运算后的结果无法返回到主线程中,主线程拿不到修改后的值,无法更新文本框的内容,这时,使用Handler来进行线程间的数据传递 以下为DEMO public class PostActivityActivity extends Activi...

远程线程注入DLL

0x00 原理介绍:上一篇文章介绍了在Windows下如何在其他进程创建一个远程线程:https://www.cnblogs.com/DarkBright/p/10820582.html 调用 CreateRemoteThread 创建远程线程所需要的过程函数的标准形式为: DWORD WINAPI ThreadProc( _In_ LPVOID lp...

jvm内存模型和内存分配

1.什么是jvm? (1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。 (2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。 (3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改...

.net 多线程的使用(Thread)

 上篇 net 同步异步   中篇 多线程的使用(Thread)   下篇 net 任务工厂实现异步多线程 Thread多线程概述  上一篇我们介绍了net 的同步与异步,我们异步演示的时候使用的是委托多线程来实现的。今天我们来细细的剖析下 多线程。 多线程的优点:可以同时完成多个任务;可以使程序的响应速度更快;可以让占用大量处理时间的任务或当前没有进...

卡顿问题

导致卡顿问题的几种原因: 复杂 UI 、图文混排的绘制量过大; 在主线程上做网络同步请求; 在主线程做大量的 IO 操作; 运算量过大,CPU 持续高占用; 死锁和主子线程抢锁。 FPS 是一秒显示的帧数,也就是一秒内画面变化数量。当FPS达到60,说明界面很流程,当FPS低于24,页面流畅度不是那么流畅。 线程的消息 事件是依赖于 NSRunLoop...

解决mySQL占用内存超大问题

为了装mysql环境测试,装上后发现启动后mysql占用了很大的虚拟内存,达8百多兆。网上搜索了一下,得到高人指点my.ini。再也没见再详细的了..只好打开my.ini逐行的啃,虽然英文差了点,不过多少M还是看得明的^-^ 更改后如下: innodb_buffer_pool_size=576M ->256M InnoDB引擎缓冲区占了大头,首要就是...