日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件下載最安全的下載網(wǎng)站、值得信賴的軟件下載站!

      首頁編程開發(fā)C#.NET → 基于HttpWebRequest的通用請(qǐng)求和響應(yīng)處理

      基于HttpWebRequest的通用請(qǐng)求和響應(yīng)處理

      相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來源:瞿杰時(shí)間:2012/12/17 8:41:21字體大小:A-A+

      作者:Tony Qu點(diǎn)擊:0次評(píng)論:0次標(biāo)簽: 通用請(qǐng)求

      • 類型:圖像瀏覽大。13.0M語言:英文 評(píng)分:4.2
      • 標(biāo)簽:
      立即下載

      使用HttpWebRequest和HttpWebResponse在后臺(tái)進(jìn)行文件的提交,可以替代使用前臺(tái)form提交的方式,HttpWebRequest用來測(cè)試某網(wǎng)頁的速度是500多毫秒,而IE速度很快只有不到100毫秒,如何才能提高HttpWebRequest的響應(yīng)速度?

      ------解決方案--------------------------------------------------------
      看看服務(wù)器是否支持壓縮,如果服務(wù)器支持壓縮可能是因?yàn)镮E接收的是壓縮數(shù)據(jù),你的程序時(shí)接收未壓縮數(shù)據(jù),所以比IE慢。
      Httpwebrequest 的速度應(yīng)該比IE快才對(duì), 它不用渲染,HttpWebRequest是經(jīng)過層層封裝后得到的東西,IE應(yīng)該是直接調(diào)用系統(tǒng)底層的方法,所以會(huì)比較快。

      我使用過程中遇到的最大挑戰(zhàn)是以下幾個(gè)問題:
      a. 如何處理chunked的頁面
      b. 如何處理gzip過的頁面
      c. 如何自動(dòng)判斷文本編碼
      d. 如何使用CookieContainer

      我們一個(gè)一個(gè)來,先從第一個(gè)開始。chunked是常用的web服務(wù)器設(shè)置,也經(jīng)常與gzip一起使用,

      a. 如何處理chunked的頁面

      (fiddler的Response Header視圖截圖)

      chunked的好處最主要的是頁面優(yōu)化,瀏覽器通常會(huì)在接收完第一個(gè)chunked塊之后開始解析頁面,而不是等到整個(gè)頁面加載完成。關(guān)于chunked的傳輸細(xì)節(jié)有興趣的朋友可以繼續(xù)閱讀以下兩篇文章http 《chunked傳輸》
      《HTTP chunked+gzip及瀏覽器兼容測(cè)試》

      由于頁面的chunked,我們必須通過stream方式來獲得數(shù)據(jù),且由于之后要對(duì)獲得的Stream進(jìn)行g(shù)zip解密,所以我們需要把Stream暫時(shí)保存到MemoryStream中,如下所示:

      MemoryStream memory = null;
      int length = 0;
      if (res.ContentLength > 0)
      {
          length = (int)res.ContentLength;
      }
      else
      {
          length = 8000;
      }
      memory = new MemoryStream(length);
      Byte[] buf = new byte[4096];
      Stream resStream = res.GetResponseStream();
      int count = 0;
      do
      {
          count = resStream.Read(buf, 0, buf.Length);
          if (count != 0)
          {
              memory.Write(buf, 0, count);
          }
      } while (count > 0);

      這里利用ContentLength獲取實(shí)際大小,但在有些情況下,ContentLength取不到,就會(huì)有個(gè)默認(rèn)大小8000。當(dāng)然這只是MemoryStream初始,如果Write的時(shí)候超過,它會(huì)自動(dòng)增加大。ㄎ矣浀檬悄J(rèn)大小的兩倍)。

      b. 如何處理gzip

      gzip的好處想必不用我說了吧,自然是傳輸大小更小,動(dòng)態(tài)壓縮,目前大部分門戶都會(huì)打開這個(gè)選項(xiàng),其平均壓縮效果可以達(dá)到不開之前的40%左右,以下是處理gzip的代碼:

      Stream responseStream = null;
      //handle gzip or deflate stream
      if (res.ContentEncoding.ToLower().Contains("gzip"))
      {
          responseStream = new GZipStream(memory, CompressionMode.Decompress);
      }
      else if (res.ContentEncoding.ToLower().Contains("deflate"))
      {
          responseStream = new DeflateStream(memory, CompressionMode.Decompress);
      }
      else
      {
          responseStream = memory;
      }

      壓縮方式可以通過ContentEncoding屬性獲得,這里同時(shí)也處理了deflate的壓縮方式,不過目前我沒遇到過這種網(wǎng)站,這代碼是拷貝過來的,呵呵。

      c. 如何自動(dòng)判斷文本編碼

      編碼問題往往是讓人頭疼的問題,因?yàn)槟承┣闆r你拿到的數(shù)據(jù)會(huì)變成亂碼,這就表示編碼沒有處理好。頁面的實(shí)際編碼是保存在ContentType中的,如下所示

      (fiddler的Response Header視圖截圖)

      這里的charset就是我們需要的編碼信息,編碼的自動(dòng)選擇全靠它了,編碼的真正作用發(fā)生在我們把剛才的responseStream轉(zhuǎn)換為string,代碼如下所示:

      int charsetPos = res.ContentType.IndexOf("charset=");
      string encoding = "UTF-8";
      if (charsetPos >= 0)
      {
          int semicolonPos = res.ContentType.IndexOf(";", charsetPos);
          encoding = res.ContentType.Substring(charsetPos + 8, semicolonPos > 0 ? semicolonPos - charsetPos - 8 : res.ContentType.Length - charsetPos - 8);
      }
      var oEncoding = Encoding.GetEncoding(encoding);
      using (StreamReader sr = new StreamReader(responseStream, oEncoding))
      {
          content = sr.ReadToEnd();
      }

      我這邊用了比較原始的方法,沒有用正則表達(dá)式,如果你覺得這個(gè)方法很挫,你可以換成正則表達(dá)式?吹?jīng)],StreamReader通過oEncoding得知該用哪種編碼來把byte[]轉(zhuǎn)換為String。

      (這里牽扯到幾年前我做過的一道面試題:String和byte[]如何進(jìn)行轉(zhuǎn)換?說說你的經(jīng)驗(yàn)。這道題雖然很多公司不面,但我倒覺得這道題是可以深入的,因?yàn)閑ncoding其實(shí)是個(gè)很不錯(cuò)的面試話題,也很考基礎(chǔ)知識(shí)。)

      d. 如何使用CookieContainer

      通常呢,稍微有點(diǎn)防御的網(wǎng)站都會(huì)驗(yàn)cookie,或者放個(gè)身份認(rèn)證的cookie,如何在請(qǐng)求中放cookie呢,自然是靠CookieContainer(其實(shí)也可以通過AddHttpHeader,但本文只討論CookieContainer,好處等會(huì)兒說,先賣個(gè)關(guān)子。)CookieContainer的接口有點(diǎn)搞,因?yàn)榧扔蠥dd,也有SetCookie,我一開始就上了老當(dāng),用了Add,結(jié)果沒有效果。SetCookies才是正確的方法,這個(gè)方法即可以一次性設(shè)置完所有的cookie,也可以一個(gè)一個(gè)設(shè)置,如下:

      CookieContainer cookieContainer = new CookieContainer();
      cookieContainer.SetCookies(new Uri(hostname), new Cookie("aaa", "98d4c408-7923-443a-ba3f-99df3bea7792", "/", "a.com").ToString());
      cookieContainer.SetCookies(new Uri(hostname), new Cookie("bbb", "0", "/", "a.com").ToString());
      cookieContainer.SetCookies(new Uri(hostname), new Cookie("ccc", "0", "/", "a.com").ToString());
      HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
      req.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
      req.AllowAutoRedirect = true;
      req.Accept =  "text/html, application/xhtml+xml, */*"; 
      req.Timeout = 50000;
      req.Method = "GET";
      req.CookieContainer = cookieContainer;
      var response = (HttpWebResponse)req.GetResponse();

      這里使用Cookie而非直接用字符串是出于安全考慮,因?yàn)镃ookie對(duì)象的ToString自動(dòng)幫我們把encoding做掉了,所以這么寫會(huì)比直接用字符串來的安全,SetCookies是需要指定Url的,不過通常對(duì)于同一個(gè)網(wǎng)站host應(yīng)該是一樣的,比如www.a.com,不過目前還沒遇到過跨域問題,等遇到了我單獨(dú)寫一篇討論,跨域可又是另外一個(gè)頭疼的問題了。

      這里要說一下CookieContainer和AddHttpHeader的區(qū)別,首先這兩個(gè)不能同時(shí)使用,只能用一個(gè),其次CookieContainer畢竟是容器,所以理論上可以把另外一個(gè)請(qǐng)求的cookie一起帶過來,然后實(shí)現(xiàn)cookie傳遞邏輯,而AddHttpHeader做不到這一點(diǎn),這是最大的區(qū)別。

      先寫到這,大家有什么關(guān)于HttpWebRequest的其他心得可以發(fā)在回復(fù)中,我會(huì)整理后更新這個(gè)帖子。

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過審核才能顯示)