Liny_@NotePad

沉迷ACG中

<C#高级编程>第31章笔记(上)

YOYO posted @ 2010年3月10日 20:39 in 【C#】 with tags C#高级编程 网络编程 , 2720 阅读

第31章的内容是访问Internet,本文作关于WebClient、WebRequest和WebResponse获取Web资源的笔记。

贴个图,本章的例子,以下是Form及对应的控件名,实现输入URL后获得页面内容:

31 访问Internet


先贴贴前文中的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace TestWebClient
{
    public partial class WebClientForm : Form
    {
        public WebClientForm()
        {
            InitializeComponent();
        }

        private void button_Click(object sender, EventArgs e)
        {
            //  清空文本框
            content.Clear();

            //  创建WebClient对象
            WebClient client = new WebClient();

            //  创建流引用
            Stream stream = null;

            //  创建流读取对象引用
            StreamReader reader = null;

            try
            {
                //  获得输入流
                stream = client.OpenRead(url.Text);

                //  获得输入流读取对象
                reader = new StreamReader(stream);

                //  读取数据并追加到文本框末尾
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    content.AppendText(line + "\n");
                }
            }
            catch (Exception ex)
            {
                //  遇到Exception,提示错误信息
                content.Text = ex.ToString();
            }
            finally
            {
                //  关闭输入流读取对象
                if (reader != null)
                {
                    reader.Close();
                }

                //  关闭输入流
                if (stream != null)
                {
                    stream.Close();
                }

                //  释放WebClient资源
                client.Dispose();
            }
        }
    }
}

WebClient具备了包括检索数据(OpenRead()方法)、写数据(OpenWrite()方法)、下载文件数据(DownloadFile()、DownloadData()方法)、上传文件数据(UploadFile()、UploadData()方法)等基本功能,

但是由于它是通用的,功能非常有限,不能处理任一协议的任何附加特性,例如HTTP协议中的Cookie。

此时我们通常用System.Net命名空间中以WebRequest类和WebResponse类为基类的一系列类。

例如对于HTTP协议,就可以使用HttpWebRequestHttpWebResponse类。

另外,WebRequest有一个属性Credentials,可以将身份验证证书(NetworkCredential)附带在请求中。

 

下面是修改button_Click()方法,改用WebRequest和WebResponse实现的一个例子:

        private void button_Click(object sender, EventArgs e)
        {
            //  清空文本框
            content.Clear();

            //  创建WebRequest对象引用
            WebRequest request = null;

            //  创建WebResponse对象引用
            WebResponse response = null;
           
            //  创建流引用
            Stream stream = null;
            //  创建流读取对象引用
            StreamReader reader = null;

            try
            {
                //  创建请求
                request = WebRequest.Create(url.Text);

                //  获得回应
                response = request.GetResponse();

                //  获得输入流
                stream = response.GetResponseStream();

                //  获得输入流读取对象
                reader = new StreamReader(stream);

                //  读取数据并追加到文本框末尾
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    content.AppendText(line + "\n");
                }
            }
            catch (Exception ex)
            {
                //  遇到Exception,提示错误信息
                content.Text = ex.ToString();
            }
            finally
            {
                //  关闭输入流读取对象
                if (reader != null)
                {
                    reader.Close();
                }

                //  关闭输入流
                if (stream != null)
                {
                    stream.Close();
                }

                //  关闭WebResponse
                if (response != null)
                {
                    response.Close();
                }

                //  关闭WebRequest
                if (request != null)
                {
                    request.Abort();
                }
            }
        }

WebRequest类的另一个特性就是可以异步请求页面,通过BeginGetResponse()EndGetResponse()方法。

BeginGetResponse()方法执行时管理一个后台进程,并返回IAsyncResult接口,

再通过EndGetResponse()方法获得结果。

* 注意,由于两个并非同一线程,修改控件值时VS会警告,这里参考了MSDN里面的样例代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace TestWebClient
{
    public partial class AsynForm : Form
    {
        //  委托
        delegate void ChangeContentCallback(string text);

        public AsynForm()
        {
            InitializeComponent();
        }

        private void button_Click(object sender, EventArgs e)
        {
            //  清空文本框
            content.Clear();

            //  创建请求
            WebRequest request = WebRequest.Create(url.Text);

            //  开始异步接收
            request.BeginGetResponse(new AsyncCallback(OnResponse), request);
        }

        //  回调方法
        protected void OnResponse(IAsyncResult ar)
        {
            //  创建请求对象引用
            WebRequest request = null;

            //  创建回应对象引用
            WebResponse response = null;

            //  创建流引用
            Stream stream = null;

            //  创建输入流读取对象引用
            StreamReader reader = null;

            try
            {
                //  获得请求对象
                request = (WebRequest)ar.AsyncState;

                //  获得回应
                response = request.EndGetResponse(ar);

                //  获得输入流
                stream = response.GetResponseStream();

                //  获得输入流读取对象
                reader = new StreamReader(stream);

                //  读取数据并追加到文本框末尾
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    this.AppendContent(line + "\n");
                }
            }
            catch (Exception ex)
            {
                //  遇到Exception,提示错误信息
                this.SetContent(ex.ToString());
            }
            finally
            {
                //  关闭输入流读取对象
                if (reader != null)
                {
                    reader.Close();
                }

                //  关闭输入流
                if (stream != null)
                {
                    stream.Close();
                }

                //  关闭WebResponse
                if (response != null)
                {
                    response.Close();
                }

                //  关闭WebRequest
                if (request != null)
                {
                    request.Abort();
                }
            }
        }

        //  对 Windows 窗体控件进行线程安全调用
        private void SetContent(string text)
        {
            if (this.content.InvokeRequired)
            {
                ChangeContentCallback d = new ChangeContentCallback(SetContent);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.content.Text = text;
            }
        }

        //  对 Windows 窗体控件进行线程安全调用
        private void AppendContent(string text)
        {
            if (this.content.InvokeRequired)
            {
                ChangeContentCallback d = new ChangeContentCallback(AppendContent);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.content.AppendText(text);
            }
        }

    }
}

既然都是M$家的,就可以考虑是否将网页内容以浏览器显示。

书上给出了两种办法:

 

第一种是通过调用IE,打开浏览器窗口显示Web页面:

            Process process = new Process();
            process.StartInfo.FileName = "iexplore.exe";
            process.StartInfo.Arguments = url.Text;
            process.Start();

第二种是通过工具箱里的浏览器控件,这样就可以将浏览器嵌入应用程序中操作:

            byte[] postDatas = new byte[0];
            string emptyString = "";
            object oEmptyString = emptyString;

            browser.Navigate(   url.Text,           //  URL字符串
                                emptyString,        //  显示资源的目标帧(如果有)
                                postDatas,          //  POST数据
                                emptyString         //  HTTP标题信息
                             );

也许是版本问题,书上的Navigate方法有5个参数,在VS 2005里最多只有4个参数。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter