欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程(下)

 更新時(shí)間:2020年06月15日 17:15:29   作者:一線碼農(nóng)  
這篇文章主要介紹了深入學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程的相關(guān)知識(shí),文中講解的非常詳細(xì),幫助大家更好的學(xué)習(xí)c#網(wǎng)絡(luò)編程,感興趣的朋友可以了解下

       第三篇來的好晚啊,上一篇說了如何向服務(wù)器推送信息,這一篇我們看看如何"快好準(zhǔn)"的從服務(wù)器下拉信息。

       網(wǎng)絡(luò)上有很多大資源文件,比如供人下載的zip包,電影(你懂的),那么我們?nèi)绾慰焖俚倪M(jìn)行下載,大家第一反應(yīng)肯定就是多線程下載,

那么這些東西是如何做的呢?首先我們可以從“QQ的中轉(zhuǎn)站里面拉一個(gè)rar下來“。

然后用fiddler監(jiān)視一下,我們會(huì)發(fā)現(xiàn)一個(gè)有趣的現(xiàn)象:

第一:7.62*1024*1024≈7990914  千真萬確是此文件

第二:我明明是一個(gè)http鏈接,tmd的怎么變成n多個(gè)了?有意思。

好,我們繼續(xù)往下看,看看這些鏈接都做了些什么?

最終,我們發(fā)現(xiàn)http協(xié)議中有一個(gè)Conent—Range字段,能夠把我們的文件總大小進(jìn)行切分,然后并行下載,最后再進(jìn)行合并,大概我們知道了什么原理,那么,我們強(qiáng)大的C#類庫提供了AddRange來獲取Http中資源的指定范圍。

既然進(jìn)行了切分,那么首先一定要知道文件的ContentLength是多少,如果對(duì)http協(xié)議比較熟悉的話,當(dāng)發(fā)送一個(gè)頭信息過去,服務(wù)器返回的頭信息中會(huì)包含很多東西,此時(shí)我們就知道要下載資源的大概情況,這個(gè)就有點(diǎn)“兵馬未動(dòng),糧草先行“的感覺。

var request = (HttpWebRequest)HttpWebRequest.Create(url);

   request.Method = "Head";

   request.Timeout = 3000;

   var response = (HttpWebResponse)request.GetResponse();

   var code = response.StatusCode;

   if (code != HttpStatusCode.OK)
   {
    Console.WriteLine("下載資源無效!");
    return;
   }

   var total = response.ContentLength;

這里有個(gè)決策,到底是以下載量來決定線程數(shù),還是以線程數(shù)來決定下載量,由于我們的下載取決于當(dāng)前的網(wǎng)速,所以在這種場(chǎng)合下更好的方案是

采用后者,這幾天在閃存里面兩次看到蒼老師,肅然起敬,所以決定在不用線程和線程的情況下,看看下載倉老師的速度如何。

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Net;
 using System.Threading;
 using System.Threading.Tasks;
 using System.IO;
 using System.Collections.Concurrent;
 using System.Diagnostics;
 using System.Drawing;
 
 
 namespace ConsoleApplication1
 {
  public class Program
  {
   public static CountdownEvent cde = new CountdownEvent(0);
 
   //每個(gè)線程下載的字節(jié)數(shù),方便最后合并
   public static ConcurrentDictionary<long, byte[]> dic = new ConcurrentDictionary<long, byte[]>();
 
   //請(qǐng)求文件
   public static string url = "http://www.dbjr.com.cn/";
 
   static void Main(string[] args)
   {
    for (int i = 0; i < 1; i++)
    {
     Console.WriteLine("\n****************************\n第{0}次比較\n****************************", (i + 1));
 
     //不用線程
     //RunSingle();
 
     //使用多線程
     RunMultiTask();
    }
 
    Console.Read();
   }
 
   static void RunMultiTask()
   {
    Stopwatch watch = Stopwatch.StartNew();
 
    //開5個(gè)線程
    int threadCount = 5;
 
    long start = 0;
 
    long end = 0;
 
    var total = GetSourceHead();
 
    if (total == 0)
     return;
 
    var pageSize = (int)Math.Ceiling((Double)total / threadCount);
 
    cde.Reset(threadCount);
 
    Task[] tasks = new Task[threadCount];
 
    for (int i = 0; i < threadCount; i++)
    {
     start = i * pageSize;
 
     end = (i + 1) * pageSize - 1;
 
     if (end > total)
      end = total;
 
     var obj = start + "|" + end;
 
     tasks[i] = Task.Factory.StartNew(j => new DownFile().DownTaskMulti(obj), obj);
    }
 
    Task.WaitAll(tasks);
 
    var targetFile = "C://" + url.Substring(url.LastIndexOf('/') + 1);
 
    FileStream fs = new FileStream(targetFile, FileMode.Create);
 
    var result = dic.Keys.OrderBy(i => i).ToList();
 
    foreach (var item in result)
    {
     fs.Write(dic[item], 0, dic[item].Length);
    }
 
    fs.Close();
 
    watch.Stop();
 
    Console.WriteLine("多線程:下載耗費(fèi)時(shí)間:{0}", watch.Elapsed);
   }
 
   static void RunSingle()
   {
    Stopwatch watch = Stopwatch.StartNew();
 
    if (GetSourceHead() == 0)
     return;
 
    var request = (HttpWebRequest)HttpWebRequest.Create(url);
 
    var response = (HttpWebResponse)request.GetResponse();
 
    var stream = response.GetResponseStream();
 
    var outStream = new MemoryStream();
 
    var bytes = new byte[10240];
 
    int count = 0;
 
    while ((count = stream.Read(bytes, 0, bytes.Length)) != 0)
    {
     outStream.Write(bytes, 0, count);
    }
 
    var targetFile = "C://" + url.Substring(url.LastIndexOf('/') + 1);
 
    FileStream fs = new FileStream(targetFile, FileMode.Create);
 
    fs.Write(outStream.ToArray(), 0, (int)outStream.Length);
 
    outStream.Close();
 
    response.Close();
 
    fs.Close();
 
    watch.Stop();
 
    Console.WriteLine("不用線程:下載耗費(fèi)時(shí)間:{0}", watch.Elapsed);
   }
 
   //獲取頭信息
   public static long GetSourceHead()
   {
    var request = (HttpWebRequest)HttpWebRequest.Create(url);
 
    request.Method = "Head";
    request.Timeout = 3000;
 
    var response = (HttpWebResponse)request.GetResponse();
 
    var code = response.StatusCode;
 
    if (code != HttpStatusCode.OK)
    {
     Console.WriteLine("下載的資源無效!");
     return 0;
    }
 
    var total = response.ContentLength;
 
    Console.WriteLine("當(dāng)前資源大小為:" + total);
 
    response.Close();
 
    return total;
   }
  }
 
  public class DownFile
  {
   // 多線程下載
   public void DownTaskMulti(object obj)
   {
    var single = obj.ToString().Split('|');
 
    long start = Convert.ToInt64(single.FirstOrDefault());
 
    long end = Convert.ToInt64(single.LastOrDefault());
 
    var request = (HttpWebRequest)HttpWebRequest.Create(Program.url);
 
    request.AddRange(start, end);
 
    var response = (HttpWebResponse)request.GetResponse();
 
    var stream = response.GetResponseStream();
 
    var outStream = new MemoryStream();
 
    var bytes = new byte[10240];
 
    int count = 0;
 
    while ((count = stream.Read(bytes, 0, bytes.Length)) != 0)
    {
     outStream.Write(bytes, 0, count);
    }
 
    outStream.Close();
 
    response.Close();
 
    Program.dic.TryAdd(start, outStream.ToArray());
 
    Program.cde.Signal();
   }
  }
 }

    在下面的圖中可以看出,我們的資源被分成了n段,在217.27KB的情況下,多線程加速還不是很明顯,我們可以試試更大的文件,這里我就

在本地放一個(gè)133M的rar文件。

  //請(qǐng)求文件
  public static string url = http://localhost:56933/1.rar;

現(xiàn)在看一下效果是非常明顯的。

以上就是深入學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程(下)的詳細(xì)內(nèi)容,更多關(guān)于C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解CLR的內(nèi)存分配和回收機(jī)制

    詳解CLR的內(nèi)存分配和回收機(jī)制

    本文詳細(xì)講解了CLR的內(nèi)存分配和回收機(jī)制,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • C#中哈希表(HashTable)用法實(shí)例詳解(添加/移除/判斷/遍歷/排序等)

    C#中哈希表(HashTable)用法實(shí)例詳解(添加/移除/判斷/遍歷/排序等)

    這篇文章主要介紹了C#中哈希表(HashTable)用法,簡(jiǎn)單講述了哈希表的原理并結(jié)合實(shí)例形式詳細(xì)分析了C#針對(duì)哈希表進(jìn)行添加、移除、判斷、遍歷、排序等操作的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-06-06
  • 用?FieldMask?提高?C#?gRpc?的服務(wù)性能

    用?FieldMask?提高?C#?gRpc?的服務(wù)性能

    這篇文章主要介紹了用?FieldMask?提高?C#?gRpc?的服務(wù)性能,FieldMask?是一個(gè)?protobuf?消息,包含一個(gè)名為?paths?的字段,用于指定用于指定讀取操作返回或更新操作修改的字,下文詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2022-03-03
  • C#單位轉(zhuǎn)換器簡(jiǎn)單案例

    C#單位轉(zhuǎn)換器簡(jiǎn)單案例

    這篇文章主要為大家詳細(xì)介紹了C#單位轉(zhuǎn)換器簡(jiǎn)單案例,一個(gè)簡(jiǎn)單的winform應(yīng)用程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 在C#中對(duì)TCP客戶端的狀態(tài)封裝詳解

    在C#中對(duì)TCP客戶端的狀態(tài)封裝詳解

    本篇文章小編為大家介紹,在C#中對(duì)TCP客戶端的狀態(tài)封裝詳解,需要的朋友參考下
    2013-04-04
  • C#在Unity游戲開發(fā)中進(jìn)行多線程編程的方法

    C#在Unity游戲開發(fā)中進(jìn)行多線程編程的方法

    這篇文章主要介紹了C#在Unity游戲開發(fā)中進(jìn)行多線程編程的方法,文中總結(jié)了Unity中使用多線程的幾種方式以及一款多線程插件的介紹,需要的朋友可以參考下
    2016-04-04
  • C#(asp.net)多線程用法示例(可用于同時(shí)處理多個(gè)任務(wù))

    C#(asp.net)多線程用法示例(可用于同時(shí)處理多個(gè)任務(wù))

    這篇文章主要介紹了C#(asp.net)多線程Thread用法,可用于同時(shí)處理多個(gè)任務(wù),以簡(jiǎn)單數(shù)學(xué)運(yùn)算為例講述了Thread類實(shí)現(xiàn)多線程的相關(guān)技巧,需要的朋友可以參考下
    2016-06-06
  • C#中Json的簡(jiǎn)單處理方法

    C#中Json的簡(jiǎn)單處理方法

    這篇文章主要介紹了C#中Json的簡(jiǎn)單處理方法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • c#基礎(chǔ)系列之ref和out的深入理解

    c#基礎(chǔ)系列之ref和out的深入理解

    有過C#基礎(chǔ)知識(shí)的都應(yīng)該清楚Ref和Out的使用方法,所以下面這篇文章主要給大家介紹了關(guān)于c#基礎(chǔ)系列之ref和out的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • KMP算法的C#實(shí)現(xiàn)方法

    KMP算法的C#實(shí)現(xiàn)方法

    這篇文章主要介紹了KMP算法的C#實(shí)現(xiàn)方法,代碼簡(jiǎn)潔實(shí)用,需要的朋友可以參考下
    2014-09-09

最新評(píng)論