天天看點

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直接使用更慢(大約幾毫秒),但卻更為簡單,減少了很多細節,代碼量也比較少。

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

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 很明顯,不要求線程安全,在多線程不能正常工作。

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

public

class

Singleton {

private

static

Singleton instance =

new

Singleton();

private

Singleton (){}

public

static

Singleton getInstance() {

return

instance;

}

}

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

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;

}

}

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請求解決:

_httpClient =

new

HttpClient() { BaseAddress =

new

Uri(BASE_ADDRESS) };

//幫HttpClient熱身

_httpClient.SendAsync(

new

HttpRequestMessage {

Method =

new

HttpMethod(

"HEAD"

),

RequestUri =

new

Uri(BASE_ADDRESS +

"/"

) })

.Result.EnsureSuccessStatusCode();

三者差別清單:

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