国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > 綜合 > 正文

C#實(shí)現(xiàn)HTTP協(xié)議下的多線程文件傳輸

2024-07-21 02:25:46
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
 很多人都有過(guò)使用網(wǎng)絡(luò)螞蟻或網(wǎng)絡(luò)快車軟件下載互聯(lián)網(wǎng)文件的經(jīng)歷,這些軟件的使用可以大大加速互聯(lián)網(wǎng)上文件的傳輸速度,減少文件傳輸?shù)臅r(shí)間。這些軟件為什么有如此大的魔力呢?其主要原因是這些軟件都采用了多線程下載和斷點(diǎn)續(xù)傳技術(shù)。如果我們自己來(lái)編寫一個(gè)類似這樣的程序,也能夠快速的在互聯(lián)網(wǎng)上下載文件,那一定是非常愉快的事情。下面我就講一講如何利用c#語(yǔ)言編寫一個(gè)支持多線程下載文件的程序,你會(huì)看到利用c#語(yǔ)言編寫網(wǎng)絡(luò)應(yīng)程序是多么的容易,從中也能體會(huì)到c#語(yǔ)言中強(qiáng)大的網(wǎng)絡(luò)功能。

  首先介紹一下http協(xié)議,http亦即hpyer text transfer protocal的縮寫,它是現(xiàn)代互聯(lián)網(wǎng)上最重要的一種網(wǎng)絡(luò)協(xié)議,超文本傳輸協(xié)議位于tcp/ip協(xié)議的應(yīng)用層,是一個(gè)面向無(wú)連接、簡(jiǎn)單、快速的c/s結(jié)構(gòu)的協(xié)議。http的工作過(guò)程大體上分連接、請(qǐng)求、響應(yīng)和斷開(kāi)連接四個(gè)步驟。c#語(yǔ)言對(duì)http協(xié)議提供了良好的支持,在.net類庫(kù)中提供了webrequest和webresponse類,這兩個(gè)類都包含在system.net命名空間中,利用這兩個(gè)類可以實(shí)現(xiàn)很多高級(jí)的網(wǎng)絡(luò)功能,本文中多線程文件下載就是利用這兩個(gè)類實(shí)現(xiàn)的。 webrequest和webresponse都是抽象基類,因此在程序中不能直接作為對(duì)象使用,必須被繼承,實(shí)際使用中,可根據(jù)uri參數(shù)中的uri前綴選用它們合適的子類,對(duì)于http這類uri,httpwebrequest和httpwebresponse類可以用于處理客戶程序同web服務(wù)器之間的http通訊。

  httpwebrequest類實(shí)現(xiàn)了很多通過(guò)http訪問(wèn)web服務(wù)器上文件的高級(jí)功能。httpwebrequest類對(duì)webrequest中定義的屬性和方法提供支持,httpwebrequest將發(fā)送到internet資源的公共http標(biāo)頭的值公開(kāi)為屬性,由方法或系統(tǒng)設(shè)置,常用的由屬性或方法設(shè)置的http標(biāo)頭為:接受, 由accept屬性設(shè)置, 連接, 由connection屬性和keepalive屬性設(shè)置, content-length, 由contentlength屬性設(shè)置, content-type, 由contenttype屬性設(shè)置, 范圍, 由addrange方法設(shè)置. 實(shí)際使用中是將標(biāo)頭信息正確設(shè)置后,傳遞到web服務(wù)器,web服務(wù)器根據(jù)要求作出回應(yīng)。

  httpwebresponse類繼承自webresponse類,專門處理從web服務(wù)器返回的http響應(yīng),這個(gè)類實(shí)現(xiàn)了很多方法,具有很多屬性,可以全面處理接收到的互聯(lián)網(wǎng)信息。在httpwebresponse類中,對(duì)于大多數(shù)通用的http標(biāo)頭字段,都有獨(dú)立的屬性與其對(duì)應(yīng),程序員可以通過(guò)這些屬性方便的訪問(wèn)位于http接收?qǐng)?bào)文標(biāo)頭字段中的信息,本例中用到的httpwebresponse類屬性為:contentlength 既接收內(nèi)容的長(zhǎng)度。

  有了以上的了解后,下面看看這兩個(gè)類的用法,要?jiǎng)?chuàng)建httpwebrequest對(duì)象,不要直接使用httpwebrequest的構(gòu)造函數(shù),而要使用webrequest.create方法初始化一個(gè)httpwebrequest實(shí)例,如:

httpwebrequest hwr=(httpwebrequest)webrequest.create(http://www.163.com/);

  創(chuàng)建了這個(gè)對(duì)象后,就可以通過(guò)httpwebrequest屬性,設(shè)置很多http標(biāo)頭字段的內(nèi)容,如hwr.addrange(100,1000);設(shè)置接收對(duì)象的范圍為100-1000字節(jié)。

  httpwebreques對(duì)象使用getresponse()方法時(shí),會(huì)返回一個(gè)httpwebresponse對(duì)象,為提出http返回報(bào)文信息,需要使用httpwebresponse的getresponsestream()方法,該方法返回一個(gè)stream對(duì)象,可以讀取http返回的報(bào)文,如:首先定義一個(gè)strean 對(duì)象 public system.io.stream ns; 然后 ns=hwr.getresponse ().getresponsestream ();即可創(chuàng)建stream對(duì)象。有了以上的準(zhǔn)備知識(shí)后下面開(kāi)始設(shè)計(jì)我們的多線程互聯(lián)網(wǎng)文件的下載程序,首先打開(kāi)visual studio.net集成開(kāi)發(fā)環(huán)境,選擇“文件”、“新建”、“項(xiàng)目”,然后選擇“visual c#項(xiàng)目”,在向?qū)в疫吜斜砜蛑羞x中“windows應(yīng)用程序”,輸入項(xiàng)目名稱,如本例為:httpftp,然后選擇“確定”按鈕,向?qū)ё詣?dòng)生成了一個(gè)windows應(yīng)用程序項(xiàng)目。首先打開(kāi)窗口設(shè)計(jì)器設(shè)計(jì)應(yīng)用程序窗口,增加如下控件:

  一個(gè)列表框 listbox1 三個(gè)文本標(biāo)簽 label1-label3 三個(gè)文本框 textbox1-textbox3 一個(gè)開(kāi)始接收按鈕 button1 設(shè)計(jì)好的窗口如下圖:


  控件定義代碼是:

public system.windows.forms.listbox listbox1;
private system.windows.forms.label label1;
private system.windows.forms.textbox textbox1
private 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;

  打開(kāi)form1的代碼編輯器,增加如下的命名空間:

using system.net;//網(wǎng)絡(luò)功能
using system.io;//流支持
using system.threading ;//線程支持

  增加如下的程序變量:

public bool[] threadw; //每個(gè)線程結(jié)束標(biāo)志
public string[] filenamew;//每個(gè)線程接收文件的文件名
public int[] filestartw;//每個(gè)線程接收文件的起始位置
public int[] filesizew;//每個(gè)線程接收文件的大小
public string strurl;//接受文件的url
public bool hb;//文件合并標(biāo)志
public int thread;//進(jìn)程數(shù)
定義一個(gè)httpfile類,用于管理接收線程,其代碼如下:

public class httpfile
{
 public form1 formm;
 public int threadh;//線程代號(hào)
 public string filename;//文件名
 public string strurl;//接收文件的url
 public filestream fs;
 public httpwebrequest request;
 public system.io.stream ns;
 public byte[] nbytes;//接收緩沖區(qū)
 public int nreadsize;//接收字節(jié)數(shù)
 public httpfile(form1 form,int thread)//構(gòu)造方法
 {
  formm=form;
  threadh=thread;
 }
 ~httpfile()//析構(gòu)方法
 {
  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 ()+"開(kāi)始接收");
  fs=new filestream (filename,system.io.filemode.create);
  try
  {
   request=(httpwebrequest)httpwebrequest.create (strurl);
   //接收的起始位置及接收的長(zhǎng)度
   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 ("進(jìn)程"+threadh.tostring ()+"接收完畢!");
  formm.threadw[threadh]=true;
 }
}

  該類和form1類處于統(tǒng)一命名空間,但不包含在form1類中。下面定義“開(kāi)始接收”按鈕控件的事件響應(yīng)函數(shù):

private void button1_click(object sender, system.eventargs e)
{
 datetime dt=datetime.now;//開(kāi)始接收時(shí)間
 textbox1.text =dt.tostring ();
 strurl=textbox2.text .trim ().tostring ();
 httpwebrequest request;
 long filesize=0;
 try
 {
  request=(httpwebrequest)httpwebrequest.create (strurl);
  filesize=request.getresponse ().contentlength;//取得目標(biāo)文件的長(zhǎng)度
  request.abort ();
 }
 catch (exception er)
 {
  messagebox.show (er.message );
 }
 // 接收線程數(shù)
 thread=convert.toint32 (textbox4.text .trim().tostring (),10);
 //根據(jù)線程數(shù)初始化數(shù)組
 threadw=new bool [thread];
 filenamew=new string [thread];
 filestartw=new int [thread];
 filesizew=new int[thread];

 //計(jì)算每個(gè)線程應(yīng)該接收文件的大小
 int filethread=(int)filesize/thread;//平均分配
 int filethreade=filethread+(int)filesize%thread;//剩余部分由最后一個(gè)線程完成
 //為數(shù)組賦值
 for (int i=0;i<thread;i++)
 {
  threadw[i]=false;//每個(gè)線程狀態(tài)的初始值為假
  filenamew[i]=i.tostring ()+".dat";//每個(gè)線程接收文件的臨時(shí)文件名
  if (i<thread-1)
  {
   filestartw[i]=filethread*i;//每個(gè)線程接收文件的起始點(diǎn)
   filesizew[i]=filethread-1;//每個(gè)線程接收文件的長(zhǎng)度
  }
  else
  {
   filestartw[i]=filethread*i;
   filesizew[i]=filethreade-1;
  }
 }
 //定義線程數(shù)組,啟動(dòng)接收線程
 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 ();
 }
 //啟動(dòng)合并各線程接收的文件線程
 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)//有未結(jié)束線程,等待
   {
    hb=false;
    thread.sleep (100);
    break;
   }
  }
  if (hb==true)//所有線程均已結(jié)束,停止等待,
  {
   break;
  }
 }
 filestream fs;//開(kāi)始合并
 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 ();//結(jié)束時(shí)間
 messagebox.show ("接收完畢!!!");
}

  至此,一個(gè)多線程下載文件的程序就大功告成了,注意在輸入本地文件名時(shí),應(yīng)按如下格式輸入:“c://test//httpftp//bin//d.htm”,因”/”后的字符在c#中是轉(zhuǎn)義字符,線程數(shù)并非越大越好,一般5個(gè)線程就可以了,該程序在visual studio.net 2002開(kāi)發(fā)環(huán)境及windows xp 操作系統(tǒng)上通過(guò)。 
 

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 莱芜市| 建始县| 安阳市| 瓦房店市| 乃东县| 吴堡县| 蓝田县| 马尔康县| 莎车县| 蕲春县| 惠来县| 襄垣县| 宁阳县| 浪卡子县| 驻马店市| 嘉兴市| 黄浦区| 元氏县| 太谷县| 耿马| 阳原县| 佛学| 紫云| 长宁县| 禄丰县| 郯城县| 彭阳县| 云浮市| 肇东市| 会东县| 阿克苏市| 桂平市| 吴旗县| 额敏县| 威宁| 同心县| 安化县| 温宿县| 巫山县| 大安市| 通渭县|