前言
最近一直在做C# winform客戶端項目,因為涉及到和服務器交互,所以研究了一下C#的HTTP網絡編程。
Http通信是通過Http請求報文和Http應答報文來實現的。
由於我開發的是客戶端,所以主要工作就在於封裝Http請求報文,以及收到應答報文后解析數據。
Http請求報文是什么樣的
如果你使用的是chrome瀏覽器,按F12就可以開啟調試模式。現在主流的瀏覽器應該都支持這個功能。隨便打開一個網頁,觸發一個超鏈接請求,應該就能抓取到Http請求報文。
舉個例子,以下是一個Http請求報文的截取內容。
我們可以看到請求報文中有很多參數,這里不一一詳解各個參數的意義。

C#中實現Http請求
我個人認為,發送Http請求報文主要有四個步驟:
1. 初始化HttpWebRequest(需要引用System.Net)
2. 封裝Http cookie
3. 封裝Http報文頭
4. 封裝請求內容,並將封裝好的請求報文用Stream類寫入流(需要引用System.IO)
5. 接收應答報文
接下來,我們一步一步來講解如何在C#中完成Http請求報文的封裝。
初始化HttpWebRequest
使用請求地址作為參數,初始化一個HttpWebRequest實例。
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(strRequestUri);
封裝Http cookie
首先,簡單說明一下Cookie。有時也用其復數形式Cookies,指某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據(通常經過加密)。本文為了示例,就以比較簡單的形式展現。
在C#中,使用Cookie類來封裝cookie,以鍵值對的形式保存。
然后,將這個封裝好的cookie添加到CookieContainer容器中,最后填入HttpWebRequest。既然是容器,顧名思義,可以添加多個cookie。
Uri uri = new Uri(strRequestUri);
Cookie cookie = new Cookie("Name", strCookie); // 設置key、value形式的Cookie
CookieContainer cookies = new CookieContainer();
cookies.Add(uri, cookie);
httpRequest.CookieContainer = cookies;
封裝Http Header
根據自己要發送的請求報文類型來填充Http報文頭。
以下是一個簡單范例:
httpRequest.Method = "Post";
httpRequest.Referer = strReferer;
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36";
httpRequest.Accept = "text/plain, */*; q=0.01";
httpRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
httpRequest.Timeout = 1000 * 30;
httpRequest.KeepAlive = true;
填充Http content,並寫入流
首先,將要寫入的內容轉為byte數組(假設是文本內容)。將數組長度填入HttpWebRequest的ContentLength字段。
通過GetRequestStream()獲取HttpWebRequest的請求流。使用這個流對象寫入數組內容。
最后,千萬不要忘記關閉流。本人在開發C#客戶端和Java服務器交互過程中,就遇到這個問題。由於忘記關閉流,Java服務器在解析請求報文時,總是提示不能識別流的結尾。
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strContent); // 編碼形式按照個人需求來設置
httpRequest.ContentLength = bytes.Length;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close(); // 不要忘記關閉流
獲得應答報文
通過流將請求報文發出去后,可以通過HttpWebRequest的GetResponse()方法來獲取HttpWebResponse。
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream responseStream = httpResponse.GetResponseStream();
StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
string strResponse = reader.ReadToEnd();
reader.Close();
responseStream.Close();
至此,Http請求過程結束。大家有疑問的地方,歡迎和我探討。
過兩天,我再整理一下上傳文件的 Http方法。
附上完整方法
{
// 初始化HttpWebRequest
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(strRequestUri);
// 封裝Cookie
Uri uri = new Uri(strRequestUri);
Cookie cookie = new Cookie("Name", strCookie); // 設置key、value形式的Cookie
CookieContainer cookies = new CookieContainer();
cookies.Add(uri, cookie);
httpRequest.CookieContainer = cookies;
// 封裝Http Header
httpRequest.Method = "Post";
httpRequest.Referer = strReferer;
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36";
httpRequest.Accept = "text/plain, */*; q=0.01";
httpRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
httpRequest.Timeout = 1000 * 30;
httpRequest.KeepAlive = true;
// 通過流寫入請求數據
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strContent); // 編碼形式按照個人需求來設置
httpRequest.ContentLength = bytes.Length;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close(); // 不要忘記關閉流
// 獲得應答報文
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream responseStream = httpResponse.GetResponseStream();
StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
string strResponse = reader.ReadToEnd();
reader.Close();
responseStream.Close();
}


