談到HTTP協(xié)議(超文本傳輸協(xié)議),HTTP協(xié)議是一個(gè)基于請求與響應(yīng)模式的、無狀態(tài)的、應(yīng)用層的協(xié)議,常基于TCP的連接方式,HTTP1.1版本中給出一種持續(xù)連接的機(jī)制,絕大多數(shù)的Web開發(fā),都是構(gòu)建在HTTP協(xié)議之上的Web應(yīng)用。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:申請域名、網(wǎng)頁空間、營銷軟件、網(wǎng)站建設(shè)、湯陰網(wǎng)站維護(hù)、網(wǎng)站推廣。
HTTP是一個(gè)屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議,由于其簡捷、快速的方式,適用于分布式超媒體信息系統(tǒng)。HTTP協(xié)議的主要特點(diǎn)可概括為:1.支持客戶/服務(wù)器模式。2.簡單快速:客戶向服務(wù)器請求服務(wù)時(shí),只需傳送請求方法和路徑。3.靈活:HTTP允許傳輸任意類型的數(shù)據(jù)對象。4.無連接:無連接的含義是限制每次連接只處理一個(gè)請求。5.無狀態(tài):HTTP協(xié)議是無狀態(tài)協(xié)議。
在.NET框架里面對HTTP協(xié)議的處理主要采用WebRequest對象,在我們的.NET項(xiàng)目中如果需要生成HTTP請求或者處理HTTP請求,會(huì)運(yùn)用HttpWebRequest和HttpWebResponse對象。在實(shí)際項(xiàng)目的開發(fā)中,有一些需求需要同地方平臺(tái)進(jìn)行數(shù)據(jù)交互,例如我們經(jīng)常使用的微信,支付寶,QQ等等平臺(tái),這就需要我們在自己的項(xiàng)目中生成對應(yīng)的HTTP請求和處理相關(guān)HTTP請求信息。
如何在我們的系統(tǒng)中后臺(tái)生成對應(yīng)的HTTP請求,這個(gè)事情就需要對HTTP協(xié)議做一個(gè)簡單的了解:
HTTP請求由三部分組成,分別是:請求行、消息報(bào)頭、請求正文。HTTP響應(yīng)也是由三個(gè)部分組成,分別是:狀態(tài)行、消息報(bào)頭、響應(yīng)正文。HTTP消息由客戶端到服務(wù)器的請求和服務(wù)器到客戶端的響應(yīng)組成。請求消息和響應(yīng)消息都是由開始行(對于請求消息,開始行就是請求行,對于響應(yīng)消息,開始行就是狀態(tài)行),消息報(bào)頭(可選),空行(只有CRLF的行),消息正文(可選)組成。
現(xiàn)在提供一個(gè)較為通用的處理HTTP請求的代碼,此部分主要是生成同步HTTP請求。
在談到.NET的同步中,需要介紹一下同步和異步的相關(guān)內(nèi)容:
同步,可以理解為在執(zhí)行完一個(gè)函數(shù)或方法之后,一直等待系統(tǒng)返回值或消息,這時(shí)程序是出于阻塞的,只有接收到返回的值或消息后才往下執(zhí)行其他的命令。
異步,執(zhí)行完函數(shù)或方法后,不必阻塞性地等待返回值或消息,只需要向系統(tǒng)委托一個(gè)異步過程,那么當(dāng)系統(tǒng)接收到返回值或消息時(shí),新航道培訓(xùn)系統(tǒng)會(huì)自動(dòng)觸發(fā)委托的異步過程,從而完成一個(gè)完整的流程。
(以上的圖都是從別處截的,感謝提供資料的博主們。)
現(xiàn)在直接給出相關(guān)代碼:
////// 訪問次數(shù)字典 /// private readonly ConcurrentDictionary_urlTryList = new ConcurrentDictionary ();
////// Post數(shù)據(jù) /// public String PostData { set; private get; }
////// 同步請求 /// /// 請求地址 /// 錯(cuò)誤重試次數(shù) public string SyncRequest(string url, int tryTimes = 3) { if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException(url); } Trace.TraceInformation(string.Concat("開始同步請求:", url)); _urlTryList.TryAdd(url, tryTimes); //創(chuàng)建并定義HTTP請求相關(guān)信息 var request = WebRequest.Create(url) as HttpWebRequest; if (request == null) return string.Empty; request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch"); request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8"); request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.None; request.Credentials = CredentialCache.DefaultNetworkCredentials; request.UseDefaultCredentials = false; request.KeepAlive = false; request.PreAuthenticate = false; request.ProtocolVersion = HttpVersion.Version10; request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); request.Timeout = 1000 * 60 * 3; request.CookieContainer = CookieContainer; request.AllowAutoRedirect = true; //判斷POST請求是否為空 if (!string.IsNullOrEmpty(PostData)) { request.ContentType = "application/x-www-form-urlencoded"; request.Method = "POST"; using (var postStream = request.GetRequestStream()) { var byteArray = Encoding.GetBytes(PostData); postStream.Write(byteArray, 0, PostData.Length); postStream.Close(); } } else { request.AllowWriteStreamBuffering = false; } try { using (var response = request.GetResponse() as HttpWebResponse) { if (response != null) { if (response.StatusCode != HttpStatusCode.OK) { Trace.TraceError(string.Concat("請求地址:", request.RequestUri, " 失敗,HttpStatusCode", response.StatusCode)); return string.Empty; } using (var streamResponse = response.GetResponseStream()) { if (streamResponse != null) { if (!IsText(response.ContentType)) { var contentEncodingStr = response.ContentEncoding; var contentEncoding = Encoding; if (!string.IsNullOrEmpty(contentEncodingStr)) contentEncoding = Encoding.GetEncoding(contentEncodingStr); var streamRead = new StreamReader(streamResponse, contentEncoding); var str = streamRead.ReadToEnd(); if (CallBackAction != null && !String.IsNullOrEmpty(str)) CallBackAction.BeginInvoke(str, request.RequestUri.ToString(), (s) => { }, null); return str; } //創(chuàng)建并指定文件夾 var fileName = string.Concat(DateTime.Now.ToString("yyyyMMdd"), "/", DateTime.Now.ToString("yyyyMMddHHmmssffff"), Path.GetExtension(request.RequestUri.AbsoluteUri)); var fileDirectory = Path.Combine(FileSavePath, DateTime.Now.ToString("yyyyMMdd")); if (!Directory.Exists(fileDirectory)) Directory.CreateDirectory(fileDirectory); try { //下載文件 using (var fileStream = new FileStream(Path.Combine(FileSavePath, fileName), FileMode.Create)) { var buffer = new byte[2048]; int readLength; do { readLength = streamResponse.Read(buffer, 0, buffer.Length); fileStream.Write(buffer, 0, readLength); } while (readLength != 0); } if (CallBackAction != null && !String.IsNullOrEmpty(fileName)) CallBackAction.BeginInvoke(fileName, request.RequestUri.ToString(), (s) => { }, null); return fileName; } catch (IOException ex) { throw new IOException(ex.Message, ex); } } } response.Close(); } } } catch (WebException ex) { Trace.TraceError(string.Concat("請求地址:", request.RequestUri, " 失敗信息:", ex.Message)); var toUrl = request.RequestUri.ToString(); if (_urlTryList.TryGetValue(toUrl, out tryTimes)) { _urlTryList.TryUpdate(toUrl, tryTimes, tryTimes - 1); if (tryTimes - 1 <= 0) { _urlTryList.TryRemove(toUrl, out tryTimes); Trace.TraceError(string.Concat("請求地址重試失敗:", request.RequestUri)); return string.Empty; } SyncRequest(toUrl); } } finally { request.Abort(); } return string.Empty; }
以上就是對相關(guān)概念和代碼的解析。有寫的不到位的地方,敬請諒解。