<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > Linux平臺的下載程序

          Linux平臺的下載程序

          作者: 時間:2007-05-14 來源:網(wǎng)絡 收藏
          有許多網(wǎng)絡文件下載工具可以在Windows平臺下很好地工作,如NetAnts、“網(wǎng)際快車”、TelePro等,還有像WebZip那樣功能強大的離線瀏覽器。這些工具使我們可以在Windows環(huán)境下很輕松地下載網(wǎng)站上的文件、目錄、網(wǎng)站的一部分,甚至整個網(wǎng)站。然而在Linux環(huán)境下,這類工具卻很少。筆者通過自己的摸索,在集成開發(fā)環(huán)境KDevelop 1.2下實現(xiàn)了一個網(wǎng)站下載程序,它支持文件級的“多線程下載”和“”。下面本文分3部分介紹實現(xiàn)這一程序的基本技術?!?
          基本原理 
          1.超級鏈接尋徑算法 
          要想靈活地下載一個網(wǎng)站的全部或部分內(nèi)容,程序就必需具備從用戶指定的URL開始,沿著它所包含的超級鏈接遍歷整個網(wǎng)站的能力。在這個基礎上根據(jù)用戶的限制,篩選出所要下載的文件?!?
          從“圖論”的角度分析,網(wǎng)站其實是一個由文件和超級鏈接組成的“連通有向圖”。文件是圖中的頂點,超級鏈接是有向邊。我們需要對這個有向圖進行“廣度優(yōu)先遍歷”。為此,需要用一個隊列URLQueue來存放待訪問的目標。初始情況下,隊列中只含有用戶指定的那個URL。程序從隊頭取得下載目標的URL,如果它符合用戶的限制,就下載它指向的文件。分析此文件,找出其中包括的超級鏈接,生成新的下載目標的URL,然后將它們插入到隊列尾部。重復以上過程,直到隊列中沒有符合用戶限制的URL為止。 
          由于網(wǎng)站是一個“連通有向圖”,所以沿著超級鏈接,很可能回到已經(jīng)訪問過的文件。為了避免程序出現(xiàn)死循環(huán),要登記已經(jīng)訪問過的目標。在分析下載文件的超級鏈接時,我們要將生成的新目標的URL與已經(jīng)訪問過的進行比較,剔除會造成重復訪問的URL。為了提高查詢速度,我們采用了“哈希表”來存放從隊頭取出的URL。“哈希函數(shù)”可以采用將URL中的字符作為整型值相加,然后模一個質(zhì)數(shù)的簡單方法來實現(xiàn)。在本文介紹的程序中使用了質(zhì)數(shù)103。 
          2.多線程下載和 
          多線程下載和使用了同一個技術。HTTP協(xié)議允許客戶端在向服務器端發(fā)送下載一個文件的GET請求時,使用“Range: bytes=a1-a2選項,要求服務器只傳送指定文件中從第a1個字節(jié)到a2個字節(jié)之間的部分內(nèi)容。因此下載一個文件時,可以將其分成若干段,然后啟動多個線程,同時與服務器建立鏈接,分別傳送一個文件的多個部分。最后在本地將其拼接成一個完整的文件。由于從網(wǎng)上下載文件時,瓶頸是在服務器端和網(wǎng)絡傳輸過程中,所以采用多線程同時下載將大大提高下載速度?!?
          當文件傳輸因出現(xiàn)問題而中斷時,程序可以將各個線程當前下載的進度和已經(jīng)下載的內(nèi)容當做“斷點信息”保存到文件中。用戶下一次下載同一目標時,程序可以根據(jù)文件中保留的斷點信息下載上次未完成的部分,然后將整個文件拼接起來,完成下載工作。這種技術對于在經(jīng)常“掉線”的情況下下載大文件非常有利。因此,在當前流行的下載軟件中都采用了此項技術?!?
          Linux如何啟動線程 
          1.定義一個以void?。獮閰?shù)、返回void?。暮瘮?shù)。例如,為了啟動下載線程,需要定義如下函數(shù): 
          void?。tart(void?。rg) 
          { 
          ((CWebCopy?。? arg)->DownLoad(); 
          return arg; 
          } 
          2.在需要啟動線程時,只要三條語句。例如,啟動下載線程的代碼如下: 
          #include  
          pthread_t tid; 
          pthread_create(&tid,NULL,start,arg); 
          部分程序的實現(xiàn) 
           
          以下是下載線程中三個關鍵性函數(shù)的算法描述(假定這三個函數(shù)都被封裝在CwebCopy類中)?!?
          int CWebCopy::DownLoad(char?。ost,char?。猵ath,int a1,int a2,BYTE?。uf) 
          { 
          //本函數(shù)從host所指定的HTTP服務器上下載路徑為path的文件中從第a1字節(jié)到第a2字節(jié)的內(nèi)容,與host所指定的主機的80端口(HTTP端口)建立流式鏈接,共嘗試5次  
          bool connected = false; 
          int sock; //用于存放套接字描述符 
          for(i = 0; i  5 ; i++){ 
          if((sock = Connect(host,80))  0) 
          sleep(1); 
          else{ 
          connected = true; 
          break; 
          }  
          }  
          if(connected){ 
          //向指定的HTTP服務器發(fā)送GET請求,下載當前指定路徑下的文件的一部分  
          Send(sock,“GET path%cHost:?。%cRange: bytes=%d-%d%c”,path,10,host,10,a1,a2,10);  
          int inflen,index = 0; 
          while(1){ 
          struct timeval tv; 
          tv.tv_sec = 1; 
          tv.tv_usec = 0; 
          //檢查套接字是否接收到了數(shù)據(jù),嘗試20次,每次間隔1秒  
          int readen; 
          readen =ReadEn(sock,tv,20);  
          //如果套接字中20秒內(nèi)仍然沒有數(shù)據(jù),則認為超時 
          if(readen  1) return?。?;  
          //接收數(shù)據(jù),并存放在信息緩沖區(qū)中 
          inflen=read(sock,(buf+index),a2-a1); // 如果此文件所需部分已經(jīng)下載結(jié)束 
          if(inflen = 0) break; 
          } 
          return 0; 
          } 
          else return?。?; 
          } 
          int CWebCopy ::Send(int sock,char *fmt,...) 
          { 
          //本函數(shù)將指定的字符串發(fā)送到sock所指向的遠程HTTP服務器 
          char BUF[1024]; 
          va_list argptr; 
          //處理可變個數(shù)參數(shù)  
          va_start(argptr,fmt); 
          //將參數(shù)整理成字符串后放入BUF中  
          vsprintf(BUF,fmt,argptr); 
          va_end(argptr); 
          //將BUF中的字符串發(fā)送到sock所指向的遠程服務器 
          return send(sock ,BUF,strlen(BUF),0); 
          } 
          int CWebCopy ::ReadEn(int sock,struct timeval tv,int tryloop) 
          { 
          //利用select函數(shù)檢驗套接字sock,如果套接字接收到數(shù)據(jù)則返回“讀使能”,如果出現(xiàn)“內(nèi)部中斷”以外的錯誤,則返回 “讀禁止” 
          fd_set rfdset; 
          FD_ZERO(&rfdset); 
          FD_SET(sock,&rfdset); 
          int readen = 0; 
          for(int i = 0; i  tryloop; i++){ 
          readen = select(m_sock+1,&rfdset,NULL,NULL,&tv); 
          if(readen>0||(readen 0?。ΓΑrrno !=EINTR)) 
          break; 
          sleep(1); 
          } 
          return readen; 
          }


          關鍵詞: 斷點續(xù)傳

          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();