C#中HttpWebRequest、WebClient、HttpClient的使用詳解
HttpWebRequest:
命名空間: System.Net,這是.NET創(chuàng)建者最初開(kāi)發(fā)用于使用HTTP請(qǐng)求的標(biāo)準(zhǔn)類(lèi)。使用HttpWebRequest可以讓開(kāi)發(fā)者控制請(qǐng)求/響應(yīng)流程的各個(gè)方面,如 timeouts, cookies, headers, protocols。另一個(gè)好處是HttpWebRequest類(lèi)不會(huì)阻塞UI線(xiàn)程。例如,當(dāng)您從響應(yīng)很慢的API服務(wù)器下載大文件時(shí),您的應(yīng)用程序的UI不會(huì)停止響應(yīng)。HttpWebRequest通常和WebResponse一起使用,一個(gè)發(fā)送請(qǐng)求,一個(gè)獲取數(shù)據(jù)。HttpWebRquest更為底層一些,能夠?qū)φ麄€(gè)訪(fǎng)問(wèn)過(guò)程有個(gè)直觀(guān)的認(rèn)識(shí),但同時(shí)也更加復(fù)雜一些。
//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是一種更高級(jí)別的抽象,是HttpWebRequest為了簡(jiǎn)化最常見(jiàn)任務(wù)而創(chuàng)建的,使用過(guò)程中你會(huì)發(fā)現(xiàn)他缺少基本的header,timeoust的設(shè)置,不過(guò)這些可以通過(guò)繼承httpwebrequest來(lái)實(shí)現(xiàn)。相對(duì)來(lái)說(shuō),WebClient比WebRequest更加簡(jiǎn)單,它相當(dāng)于封裝了request和response方法,不過(guò)需要說(shuō)明的是,Webclient和WebRequest繼承的是不同類(lèi),兩者在繼承上沒(méi)有任何關(guān)系。使用WebClient可能比HttpWebRequest直接使用更慢(大約幾毫秒),但卻更為簡(jiǎn)單,減少了很多細(xì)節(jié),代碼量也比較少。
public class WebClientHelper
{
public static string DownloadString(string url)
{
WebClient wc = new WebClient();
//wc.BaseAddress = url; //設(shè)置根目錄
wc.Encoding = Encoding.UTF8; //設(shè)置按照何種編碼訪(fǎng)問(wèn),如果不加此行,獲取到的字符串中文將是亂碼
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); //新建一個(gè)讀取流,用指定的編碼讀取,此處是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); //下載到字節(jié)數(shù)組
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()); //觸發(fā)事件的對(duì)象
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引入的一個(gè)HTTP客戶(hù)端庫(kù),其命名空間為 System.Net.Http ,.NET 4.5之前我們可能使用WebClient和HttpWebRequest來(lái)達(dá)到相同目的。HttpClient利用了最新的面向任務(wù)模式,使得處理異步請(qǐng)求非常容易。它適合用于多次請(qǐng)求操作,一般設(shè)置好默認(rèn)頭部后,可以進(jìn)行重復(fù)多次的請(qǐng)求,基本上用一個(gè)實(shí)例可以提交任何的HTTP請(qǐng)求。HttpClient有預(yù)熱機(jī)制,第一次進(jìn)行訪(fǎng)問(wèn)時(shí)比較慢,所以不應(yīng)該用到HttpClient就new一個(gè)出來(lái),應(yīng)該使用單例或其他方式獲取HttpClient的實(shí)例
單例模式:
單例模式(Singleton Pattern)這種類(lèi)型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。
這種模式涉及到一個(gè)單一的類(lèi),該類(lèi)負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有單個(gè)對(duì)象被創(chuàng)建。這個(gè)類(lèi)提供了一種訪(fǎng)問(wèn)其唯一的對(duì)象的方式,可以直接訪(fǎng)問(wèn),不需要實(shí)例化該類(lèi)的對(duì)象。
單例創(chuàng)建步驟:1、定義靜態(tài)私有對(duì)象;2、定義私有構(gòu)造函數(shù);3、提供公共獲取對(duì)象方法;
單例模式一般分為兩種實(shí)現(xiàn)模式:懶漢模式、餓漢模式(以下為Java代碼實(shí)現(xiàn))
懶漢模式: 默認(rèn)不會(huì)實(shí)例化,什么時(shí)候用什么時(shí)候new
public class Singleton {
private static Singleton instance = null;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
這種方式是最基本的實(shí)現(xiàn)方式,這種實(shí)現(xiàn)最大的問(wèn)題就是不支持多線(xiàn)程。因?yàn)闆](méi)有加鎖 synchronized,所以嚴(yán)格意義上它并不算單例模式。
這種方式 lazy loading 很明顯,不要求線(xiàn)程安全,在多線(xiàn)程不能正常工作。
餓漢模式: 類(lèi)初始化時(shí),會(huì)立即加載該對(duì)象,線(xiàn)程天生安全,調(diào)用效率高
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
雙檢鎖/雙重校驗(yàn)鎖(DCL,即 double-checked locking):這種方式采用雙鎖機(jī)制,安全且在多線(xiàn)程情況下能保持高性能
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:
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異步請(qǐng)求方法
{
try
{
HttpContent content = new StringContent(strJson);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
//由HttpClient發(fā)出異步Post請(qǐng)求
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同步請(qǐng)求方法
{
try
{
HttpContent content = new StringContent(strJson);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
//client.DefaultRequestHeaders.Connection.Add("keep-alive");
//由HttpClient發(fā)出Post請(qǐng)求
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有預(yù)熱機(jī)制,第一次請(qǐng)求比較慢;可以通過(guò)初始化前發(fā)送一次head請(qǐng)求解決:
_httpClient = new HttpClient() { BaseAddress = new Uri(BASE_ADDRESS) };
//幫HttpClient熱身
_httpClient.SendAsync(new HttpRequestMessage {
Method = new HttpMethod("HEAD"),
RequestUri = new Uri(BASE_ADDRESS + "/") })
.Result.EnsureSuccessStatusCode();
三者區(qū)別列表:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# Socket編程實(shí)現(xiàn)簡(jiǎn)單的局域網(wǎng)聊天器的示例代碼
這篇文章主要介紹了C# Socket編程實(shí)現(xiàn)簡(jiǎn)單的局域網(wǎng)聊天器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
Unity報(bào)錯(cuò)InvalidOperationException: out of sync的解決
今天在做個(gè)東西,發(fā)現(xiàn)報(bào)錯(cuò),特此來(lái)記錄一下,本文介紹了Unity報(bào)錯(cuò)InvalidOperationException: out of sync的解決,感興趣的可以了解一下2021-05-05
字符串和十六進(jìn)制之間的轉(zhuǎn)換方法實(shí)例
這篇文章介紹了字符串和十六進(jìn)制之間的轉(zhuǎn)換方法實(shí)例,有需要的朋友可以參考一下2013-11-11
C#實(shí)現(xiàn)拷貝文件到另一個(gè)文件夾下
這篇文章主要介紹了C#實(shí)現(xiàn)拷貝文件到另一個(gè)文件夾下,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
使用C#實(shí)現(xiàn)上位機(jī)與PLC通信的過(guò)程詳解
隨著工業(yè)自動(dòng)化技術(shù)的不斷發(fā)展,PLC(可編程邏輯控制器)已成為現(xiàn)代生產(chǎn)過(guò)程中不可或缺的設(shè)備,為了實(shí)現(xiàn)設(shè)備之間的數(shù)據(jù)交換和遠(yuǎn)程控制,上位機(jī)系統(tǒng)需要與PLC進(jìn)行通信,在本文中,我們將從零開(kāi)始,介紹如何使用C#實(shí)現(xiàn)上位機(jī)與PLC的通信,需要的朋友可以參考下2025-01-01
C#高效比較兩個(gè)DataTable數(shù)據(jù)差異化的方法實(shí)現(xiàn)
本文主要介紹了C#高效比較兩個(gè)DataTable數(shù)據(jù)差異化的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

