[C#.NET][TCP Socket] 使用 HttpWebRequest 與 HttpWebResponse 類別取得伺服器資訊
Http通訊協定的流程大概是這樣
在.NET裡我們可以使用HttpWebRequest 與 HttpWebResponse 類別來建立 Server 的連線。
使用流程就像下圖,本篇將先介紹GetReponse()的用法,接下來看看實作的過程:
1.建立 HttpWebRequest 物件時無法使用建構函數,必須要使用 WebRquest 抽像類別的 Create() 方法建立。
Uri _uri = new Uri("http://www.dotblogs.com.tw/); HttpWebRequest _request = (HttpWebRequest)WebRequest.Create(url);
2.建立請求後,可觀察一下所得到的HttepWebRequest資料
const string url = "http://www.dotblogs.com.tw/"; HttpWebRequest _request = null; HttpWebResponse _response = null; Uri _uri = null; private void Form1_Load(object sender, EventArgs e) { this._uri = new Uri(url); } private void button1_Click(object sender, EventArgs e) { listBox1.Items.Clear(); this._request = (HttpWebRequest)WebRequest.Create(url); this._request.Method = WebRequestMethods.Http.Get;//預設為GET this.listBox1.Items.Add("用戶實際回應要求的URI:" + this._request.Address.ToString()); this.listBox1.Items.Add("是否允許重新導向回應:" + this._request.AllowAutoRedirect.ToString()); this.listBox1.Items.Add("是否允許緩衝傳送資料:" + this._request.AllowWriteStreamBuffering.ToString()); this.listBox1.Items.Add("用戶端安全性憑證:" + this._request.ClientCertificates.ToString()); if (this._request.Connection != null) this.listBox1.Items.Add("與伺服端保持持續性的連結至下達close參數為止:" + this._request.Connection.ToString()); if (this._request.ConnectionGroupName != null) this.listBox1.Items.Add("連結群組名稱:" + this._request.ConnectionGroupName.ToString()); if (this._request.ContentLength != -1) this.listBox1.Items.Add("傳送資料內容的大小:" + this._request.ContentLength.ToString()); if (this._request.ContentType != null) this.listBox1.Items.Add("傳送資料內容的MIME格式:" + this._request.ContentType.ToString()); this.listBox1.Items.Add("是否已接收HTTP伺服端的回應:" + this._request.HaveResponse.ToString()); this.listBox1.Items.Add("是否已接收HTTP在HTTP請求完成之後,是否關閉與HTTP伺服端之連結:" + this._request.KeepAlive.ToString()); this.listBox1.Items.Add("媒體類型:" + this._request.MaximumAutomaticRedirections.ToString()); if (this._request.MediaType != null) this.listBox1.Items.Add("媒體類型:" + this._request.MediaType.ToString()); this.listBox1.Items.Add("通訊協定方法:" + this._request.Method.ToString()); this.listBox1.Items.Add("是否要求預先驗證:" + this._request.PreAuthenticate.ToString()); this.listBox1.Items.Add("HTTP通訊協定的版本:" + this._request.ProtocolVersion.ToString()); }
3.接下來利用HttpWebRequest.GetResponse方法來取得HttpWebResponse物件
private void button2_Click(object sender, EventArgs e) { if (this._request==null) return; this.listBox2.Items.Clear(); this._response = (HttpWebResponse)this._request.GetResponse(); HttpStatusCode code = this._response.StatusCode; int idNumber = (int)code; this.listBox2.Items.Add("回應的字元編碼格式:" + this._response.CharacterSet.ToString()); this.listBox2.Items.Add("回應的壓縮及編碼格式:" + this._response.CharacterSet.ToString()); this.listBox2.Items.Add("回應資料內容的大小:" + this._response.ContentLength.ToString()); this.listBox2.Items.Add("回應資料內容的MIME格式:" + this._response.ContentType.ToString()); this.listBox2.Items.Add("最近修改回應內容的日期時間:" + this._response.LastModified.ToString()); this.listBox2.Items.Add("回應通訊協定的版本:" + this._response.ProtocolVersion.ToString()); this.listBox2.Items.Add("伺服端所回應的URI:" + this._response.ResponseUri.ToString()); this.listBox2.Items.Add("傳送回應的伺服器名稱:" + this._response.Server.ToString()); this.listBox2.Items.Add("回應訊息狀態的編碼編號:" + idNumber.ToString()); this.listBox2.Items.Add("回應訊息狀態的編碼狀態:" + this._response.StatusCode.ToString()); this.listBox2.Items.Add("回應訊息狀態的描述:" + this._response.StatusDescription.ToString()); this._response.Close(); }
特別提一下上段程式碼有使用到 HttpStatusCode 列舉型別,這是伺服器回應後所拋出的訊息,用來告訴使用者回應的狀況是否正確。
GetResponse非同步方法是 BeginGetResponse 跟 EndGetResponse;BeginGetResponse是開始非同步作業,EndGetResponse則是取得非同步資料。
HttpWebRequest request = Result.AsyncState as HttpWebRequest; HttpWebResponse response = request.EndGetResponse(Result) as HttpWebResponse;//取得資料
完整範例如下:
private void button3_Click(object sender, EventArgs e) { if (this._request == null) return; this.listBox2.Items.Clear(); RequestState state = new RequestState(); IAsyncResult result = (IAsyncResult)this._request.BeginGetResponse(new AsyncCallback(Callback), this._request); } void Callback(IAsyncResult Result) { HttpWebRequest request = Result.AsyncState as HttpWebRequest; HttpWebResponse response = request.EndGetResponse(Result) as HttpWebResponse;//取得資料 HttpStatusCode code = response.StatusCode; int id = (int)code; //跨執行緒更新 this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應的字元編碼格式:" + response.CharacterSet.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應的壓縮及編碼格式:" + response.CharacterSet.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應資料內容的大小:" + response.ContentLength.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應資料內容的MIME格式:" + response.ContentType.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "最近修改回應內容的日期時間:" + response.LastModified.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應通訊協定的版本:" + response.ProtocolVersion.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "伺服端所回應的URI:" + response.ResponseUri.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "傳送回應的伺服器名稱:" + response.Server.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應訊息狀態的編碼編號:" + id.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應訊息狀態的編碼狀態:" + response.StatusCode.ToString() }); this.BeginInvoke(new delegateUpdateControl(UpdateControl), new object[] { listBox2, "回應訊息狀態的描述:" + response.StatusDescription.ToString() }); response.Close(); }
執行結果就跟上面 button2_Click 一樣。
這個非同步方法,經我使用測試的結果,好像還是會造成主執行緒畫面卡住,真奇怪,再用一層執行緒包起來就能夠解決。
private void button4_Click(object sender, EventArgs e) { if (this._request == null) return; this.listBox2.Items.Clear(); ThreadPool.QueueUserWorkItem(new WaitCallback(PoolDoWorker)); } void PoolDoWorker(object i) { Thread t = Thread.CurrentThread; Console.WriteLine("No.{0}-Thread[{1}]:{2}", i, t.ManagedThreadId, t.ThreadState); IAsyncResult result = (IAsyncResult)this._request.BeginGetResponse(new AsyncCallback(Callback), this._request); }
在研究非同步方法時,花了很多的時間在測試畫面卡住的問題,本以為是哪個方法沒用好,最後還是選擇心中一開始就想到的路,才解決掉畫面卡住的問題,研究的過程真的很有趣,為了解決問題會看更多的資料。
使用GetResponse的例外狀況
使用GetResponseStream的例外狀況
浙公网安备 33010602011771号