C#中HttpWebRequest、WebClient、HttpClient的使用詳解


HttpWebRequest:

命名空間: System.Net,這是.NET創建者最初開發用於使用HTTP請求的標准類。使用HttpWebRequest可以讓開發者控制請求/響應流程的各個方面,如 timeouts, cookies, headers, protocols。另一個好處是HttpWebRequest類不會阻塞UI線程。例如,當您從響應很慢的API服務器下載大文件時,您的應用程序的UI不會停止響應。HttpWebRequest通常和WebResponse一起使用,一個發送請求,一個獲取數據。HttpWebRquest更為底層一些,能夠對整個訪問過程有個直觀的認識,但同時也更加復雜一些。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  //POST方法
public static string HttpPost( string Url, string postDataStr)
{
   HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
   request.Method = "POST" ;
   request.ContentType = "application/x-www-form-urlencoded" ;
   Encoding encoding = Encoding.UTF8;
   byte [] postData = encoding.GetBytes(postDataStr);
   request.ContentLength = postData.Length;
   Stream myRequestStream = request.GetRequestStream();
   myRequestStream.Write(postData, 0, postData.Length);
   myRequestStream.Close();
   HttpWebResponse response = (HttpWebResponse)request.GetResponse();
   Stream myResponseStream = response.GetResponseStream();
   StreamReader myStreamReader = new StreamReader(myResponseStream, encoding);
   string retString = myStreamReader.ReadToEnd();
   myStreamReader.Close();
   myResponseStream.Close();
 
   return retString;
}
//GET方法
public static string HttpGet( string Url, string postDataStr)
{
   HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?" ) + postDataStr);
   request.Method = "GET" ;
   request.ContentType = "text/html;charset=UTF-8" ;
   HttpWebResponse response = (HttpWebResponse)request.GetResponse();
   Stream myResponseStream = response.GetResponseStream();
   StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding( "utf-8" ));
   string retString = myStreamReader.ReadToEnd();
   myStreamReader.Close();
   myResponseStream.Close();
   return retString;
}

WebClient:

命名空間System.Net,WebClient是一種更高級別的抽象,是HttpWebRequest為了簡化最常見任務而創建的,使用過程中你會發現他缺少基本的header,timeoust的設置,不過這些可以通過繼承httpwebrequest來實現。相對來說,WebClient比WebRequest更加簡單,它相當於封裝了request和response方法,不過需要說明的是,Webclient和WebRequest繼承的是不同類,兩者在繼承上沒有任何關系。使用WebClient可能比HttpWebRequest直接使用更慢(大約幾毫秒),但卻更為簡單,減少了很多細節,代碼量也比較少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class WebClientHelper
   {
     public static string DownloadString( string url)
     {
       WebClient wc = new WebClient();
       //wc.BaseAddress = url;  //設置根目錄
       wc.Encoding = Encoding.UTF8;  //設置按照何種編碼訪問,如果不加此行,獲取到的字符串中文將是亂碼
       string str = wc.DownloadString(url);
       return str;
     }
     public static string DownloadStreamString( string url)
     {
       WebClient wc = new WebClient();
       wc.Headers.Add( "User-Agent" , "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" );
       Stream objStream = wc.OpenRead(url);
       StreamReader _read = new StreamReader(objStream, Encoding.UTF8);  //新建一個讀取流,用指定的編碼讀取,此處是utf-8
       string str = _read.ReadToEnd();
       objStream.Close();
       _read.Close();
       return str;
     }
 
     public static void DownloadFile( string url, string filename)
     {
       WebClient wc = new WebClient();
       wc.DownloadFile(url, filename);   //下載文件
     }
 
     public static void DownloadData( string url, string filename)
     {
       WebClient wc = new WebClient();
       byte [] bytes = wc.DownloadData(url);  //下載到字節數組
       FileStream fs = new FileStream(filename, FileMode.Create);
       fs.Write(bytes, 0, bytes.Length);
       fs.Flush();
       fs.Close();
     }
 
     public static void DownloadFileAsync( string url, string filename)
     {
       WebClient wc = new WebClient();
       wc.DownloadFileCompleted += DownCompletedEventHandler;
       wc.DownloadFileAsync( new Uri(url), filename);
       Console.WriteLine( "下載中。。。" );
     }
     private static void DownCompletedEventHandler( object sender, AsyncCompletedEventArgs e)
     {
       Console.WriteLine(sender.ToString());  //觸發事件的對象
       Console.WriteLine(e.UserState);
       Console.WriteLine(e.Cancelled);
       Console.WriteLine( "異步下載完成!" );
     }
 
     public static void DownloadFileAsync2( string url, string filename)
     {
       WebClient wc = new WebClient();
       wc.DownloadFileCompleted += (sender, e) =>
       {
         Console.WriteLine( "下載完成!" );
         Console.WriteLine(sender.ToString());
         Console.WriteLine(e.UserState);
         Console.WriteLine(e.Cancelled);
       };
       wc.DownloadFileAsync( new Uri(url), filename);
       Console.WriteLine( "下載中。。。" );
     }
   }

HttpClient:

HttpClient是.NET4.5引入的一個HTTP客戶端庫,其命名空間為 System.Net.Http ,.NET 4.5之前我們可能使用WebClient和HttpWebRequest來達到相同目的。HttpClient利用了最新的面向任務模式,使得處理異步請求非常容易。它適合用於多次請求操作,一般設置好默認頭部后,可以進行重復多次的請求,基本上用一個實例可以提交任何的HTTP請求。HttpClient有預熱機制,第一次進行訪問時比較慢,所以不應該用到HttpClient就new一個出來,應該使用單例或其他方式獲取HttpClient的實例

單例模式:

單例模式(Singleton Pattern)這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

單例創建步驟:1、定義靜態私有對象;2、定義私有構造函數;3、提供公共獲取對象方法;

單例模式一般分為兩種實現模式:懶漢模式、餓漢模式(以下為Java代碼實現)

懶漢模式:  默認不會實例化,什么時候用什么時候new

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
   private static Singleton instance = null ;
   private Singleton (){}
  
   public static Singleton getInstance() {
   if (instance == null ) {
     instance = new Singleton();
   }
   return instance;
   }
}

這種方式是最基本的實現方式,這種實現最大的問題就是不支持多線程。因為沒有加鎖 synchronized,所以嚴格意義上它並不算單例模式。
這種方式 lazy loading 很明顯,不要求線程安全,在多線程不能正常工作。

餓漢模式:  類初始化時,會立即加載該對象,線程天生安全,調用效率高

1
2
3
4
5
6
7
public class Singleton {
   private static Singleton instance = new Singleton();
   private Singleton (){}
   public static Singleton getInstance() {
   return instance;
   }
}

雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking):這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {
   private volatile static Singleton singleton;
   private Singleton (){}
   public static Singleton getSingleton() {
   if (singleton == null ) {
     synchronized (Singleton. class ) {
     if (singleton == null ) {
       singleton = new Singleton();
     }
     }
   }
   return singleton;
   }
}

HttpClient:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class HttpClientHelper
   {
     private static readonly object LockObj = new object ();
     private static HttpClient client = null ;
     public HttpClientHelper() {
       GetInstance();
     }
     public static HttpClient GetInstance()
     {
 
       if (client == null )
       {
         lock (LockObj)
         {
           if (client == null )
           {
             client = new HttpClient();
           }
         }
       }
       return client;
     }
     public async Task< string > PostAsync( string url, string strJson) //post異步請求方法
     {
       try
       {
         HttpContent content = new StringContent(strJson);
         content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue( "application/json" );
         //由HttpClient發出異步Post請求
         HttpResponseMessage res = await client.PostAsync(url, content);
         if (res.StatusCode == System.Net.HttpStatusCode.OK)
         {
           string str = res.Content.ReadAsStringAsync().Result;
           return str;
         }
         else
           return null ;
       }
       catch (Exception ex)
       {
         return null ;
       }
     }
 
     public string Post( string url, string strJson) //post同步請求方法
     {
       try
       {
         HttpContent content = new StringContent(strJson);
         content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue( "application/json" );
         //client.DefaultRequestHeaders.Connection.Add("keep-alive");
         //由HttpClient發出Post請求
         Task<HttpResponseMessage> res = client.PostAsync(url, content);
         if (res.Result.StatusCode == System.Net.HttpStatusCode.OK)
         {
           string str = res.Result.Content.ReadAsStringAsync().Result;
           return str;
         }
         else
           return null ;
       }
       catch (Exception ex)
       {
         return null ;
       }
     }
 
     public string Get( string url)
     {
       try
       {
         var responseString = client.GetStringAsync(url);
         return responseString.Result;
       }
       catch (Exception ex)
       {
         return null ;
       }
     }
 
   }

HttpClient有預熱機制,第一次請求比較慢;可以通過初始化前發送一次head請求解決:

1
2
3
4
5
6
7
_httpClient = new HttpClient() { BaseAddress = new Uri(BASE_ADDRESS) };
 
     //幫HttpClient熱身
     _httpClient.SendAsync( new HttpRequestMessage {
         Method = new HttpMethod( "HEAD" ),
         RequestUri = new Uri(BASE_ADDRESS + "/" ) })
       .Result.EnsureSuccessStatusCode();

三者區別列表:

 

 

出處:https://www.cnblogs.com/nnnnnn/p/13509169.html

=======================================================================================

WebClient, HttpClient, HttpWebRequest ,RestSharp之間的區別

NETCore提供了三種不同類型用於生產的REST API: HttpWebRequest;WebClient;HttpClient,開源社區創建了另一個名為RestSharp的庫。如此多的http庫,該怎樣選擇呢?

HttpWebRequest

這是.NET創建者最初開發用於使用HTTP請求的標准類。使用HttpWebRequest可以讓開發者控制請求/響應流程的各個方面,如 timeouts, cookies, headers, protocols。另一個好處是HttpWebRequest類不會阻塞UI線程。例如,當您從響應很慢的API服務器下載大文件時,您的應用程序的UI不會停止響應。

然而,強大的個性化操作帶來了極大的復雜性。為了簡單起見,GET您需要至少五行代碼;

復制代碼
HttpWebRequest http = (HttpWebRequest)WebRequest.Create("http://example.com");
                WebResponse response = http.GetResponse();
                Stream stream = response.GetResponseStream();
                using (var streamtemn = File.Create("路徑"))
                {
                    stream.CopyTo(streamtemn);
                }
復制代碼

 

如果對http協議不是了如指掌,使用HttpWebRequest會增加你的開發成本,除非你需要非常細節的處理和底層的控制,另外HttpWebRequest庫已經過時,不適合業務中直接使用,他更適用於框架內部操作。

 WebClient

WebClient是一種更高級別的抽象,是HttpWebRequest為了簡化最常見任務而創建的,使用過程中你會發現他缺少基本的header,timeoust的設置,不過這些可以通過繼承httpwebrequest來實現。使用WebClient可能比HttpWebRequest直接使用更慢(大約幾毫秒)。但這種“低效率”帶來了巨大的好處:它需要更少的代碼和隱藏了細節處理,更容易使用,並且在使用它時你不太可能犯錯誤。同樣的請求示例現在很簡單只需要兩行而且內部周到的處理完了細節:

using (WebClient webClient = new WebClient())
                {
                    webClient.DownloadFile("http://example.com", "路徑");
                }

HttpClient

HttpClient提供強大的功能,提供了異步支持,可以輕松配合async await 實現異步請求,具體使用可參考:NetCore 2.1中的HttpClientFactory最佳實踐

RestSharp

 

restsharp是開源社區貢獻,具有HttpWebRequest的細節控制和WebClient的使用簡單的優點從而讓他功能強大的同時又簡化了操作(從他定義的接口可以看出真是一個優秀的http庫啊😊)

結論

  • HttpWebRequest 已經不推薦直接使用了,這已經作為底層機制,不適合業務代碼使用
  • WebClient 不想為http細節處理而頭疼的coder而生,由於內部已經處理了通用設置,某些情況可能導致性能不是很理想
  • RestSharp 兼具強大功能和友好api很適合業務中使用
  • HttpClient 更加適用於異步編程模型中

參考:

https://stackoverflow.com/questions/22791376/is-httpwebrequest-or-webclient-faster/22792326#22792326

https://stackoverflow.com/questions/20530152/deciding-between-httpclient-and-webclient

https://social.msdn.microsoft.com/Forums/vstudio/en-US/2ce80a71-1ced-4bcd-adb4-88eef6e6a42d/httpclient-vs-httpwebrequest?forum=wcf

https://stackify.com/restsharp/?utm_referrer=https%3A%2F%2Fwww.google.com%2F

 

 

出處:https://www.cnblogs.com/xiaoliangge/p/9535027.html

=======================================================================================

.NET中 HttpWebRequest、 WebClient 、 HttpClient 的區別

1、HttpWebRequest

這是.NET創建者最初開發用於使用HTTP請求的標准類。使用HttpWebRequest可以讓開發者控制請求/響應流程的各個方面,如 timeouts, cookies, headers, protocols。另一個好處是HttpWebRequest類不會阻塞UI線程。例如,當您從響應很慢的API服務器下載大文件時,您的應用程序的UI不會停止響應。
如果對http協議不是了如指掌,使用HttpWebRequest會增加你的開發成本,除非你需要非常細節的處理和底層的控制,另外HttpWebRequest庫已經過時,不適合業務中直接使用,他更適用於框架內部操作。

創建HttpWebRequest實例時,使用WebRequest.Create方法。如果統一資源標示符的方案是http://或https://,則Create返回HttpWebRequest對象。
GetResponse方法向RequestUri屬性中指定的資源發送同步請求,並返回包含該響應的HttpWebResponse。
可以使用BeginGetResponse和EndGetResponse方法對資源發出異步請求.

當想要資源發送數據時,GetRequestStream方法返回用於發送數據的Stream對象。BeginGetRequestStream和EndGetRequestStream方法提供發送數據流的異步訪問。

發送Get請求

            //建立請求
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create("");
            //發送請求獲取Http響應
            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            //獲取響應流
            Stream receiveStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
            Console.WriteLine(reader.ReadToEnd());

發送Post請求

public static void Main()
{
    //建立請求
    HttpWebRequest request=(HttpWebRequest)WebRequest.Create("");
    request.Method="Post";
    string inputData=Console.ReadLine();
    string postData="firstnone="+inputData;
    ASCIIEncoding encoding = new ASCIIEncoding ();
    byte[] byte1=encoding.GetBytes(postData);
     
    request.ContentType = "application/x-www-form-urlencoded";
    Stream newStream = request.GetRequestStream ();
    newStream.Write (byte1, 0, byte1.Length);
      
    HttpWebResponse response=(HttpWebResponse)request.GetResponse();
    Stream myStream = HttpResp.GetResponseStream();      
    StreamReader reader = new StreamReader(myStream, code);
}

2、WebClient

WebClient是一種更高級別的抽象,是HttpWebRequest為了簡化最常見任務而創建的,使用過程中你會發現他缺少基本的header,timeoust的設置,不過這些可以通過繼承httpwebrequest來實現。使用WebClient可能比HttpWebRequest直接使用更慢(大約幾毫秒)。但這種“低效率”帶來了巨大的好處:它需要更少的代碼和隱藏了細節處理,更容易使用,並且在使用它時你不太可能犯錯誤。同樣的請求示例現在很簡單只需要兩行而且內部周到的處理完了細節:

using (WebClient webClient = new WebClient())
{
    webClient.DownloadFile("http://example.com", "路徑");
}

附一個簡單的Post請求代碼示例:

  WebClient webClient = new WebClient();
   // 向服務器發送POST數據
   byte[] responseArray = webClient.UploadValues(url, postValues);
   string response = Encoding.UTF8.GetString(responseArray);
   returns = response;

3、HttpClient

HttpClient是.NET4.5引入的一個HTTP客戶端庫,其命名空間為System.Net.Http。.NET 4.5之前我們可能使用WebClient和HttpWebRequest來達到相同目的。但是有幾點值得關注: 可以使用單個HttpClient實例發任意數目的請求
一個HttpClient實例不會跟某個HTTP服務器或主機綁定,也就是說我們可以用一個實例同時給www.a.com和www.b.com發請求
可以繼承HttpClient達到定制目的
HttpClient利用了最新的面向任務模式,使得處理異步請求非常容易.
知識點整理:

1、為了獲得HttpConet對象中的數據,在本例中使用了Result屬性,調用Result會阻塞該調用。還可以使用ReadAsStringAsync方法,這是一個異步調用。
2、Http的DefaultRequestHeaders屬性允許設置或該變標題,使用Add屬性可以給集合添加標題。設置標題后標題與標題值會與這個HttpClient實例發送的每個請求一起發送。
3、HttpClient可以把HttpMessageHandler作為其構造函數的參數,這樣就可以定制請求。可以傳遞HttpClientHandler的實例。它有許多屬性可以設置,如ClientCertificates、ContinueTimeout等。

代碼實例(Post異步請求)

 using (var client = new HttpClient(handler))
 {
     action = action.TrimEnd();
     client.DefaultRequestHeaders.Accept.Clear();
     client.DefaultRequestHeaders.Accept.Add(
     new MediaTypeWithQualityHeaderValue("application/json"));
     header = ApiHeaderCompent.AddHeader(requestUri, action, body, header, 
     HttpMethod.Post, appContext, context);
     header?.ForEach(p => client.DefaultRequestHeaders.Add(p.Key, p.Value));

     result = client.PostAsJsonAsync(requestUri + action, body).Result;
     if (!result.IsSuccessStatusCode)
         throw new Exception($"API POST 請求失敗,請求地址: {requestUri + action}");
     var data = JsonConvert.DeserializeObject<T>(result.Content.ReadAsStringAsync().Result);
   
     return new ApiResult<T>(data);
 }

 

出處:https://blog.csdn.net/u012482453/article/details/105659161/

=======================================================================================

=======================================================================================


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM