CASSINI源代码分析(2)

类别:.NET开发 点击:0 评论:0 推荐:

我们从启动程序的部分开始分析吧。

启动的入口是 Main函数,这个函数仅仅存在于CassiniWebServer ,而CassiniWebServer继承自Form类,但是我们看到,该类并没有实现代码(仅仅是提供一个入口)。在Main函数中,仅仅有两行代码:

[STAThread]

        public static int Main(String[] args) {

            Application.Run(new CassiniForm(args));

            return 0;

        }

静态方法 Application.Run在当前线程环境(STAThread)下启动一个CassiniForm的实例,启动消息循环,并且使窗体可见。

从MSDN上我们了解到:

Application 类具有用于启动和停止应用程序和线程以及处理 Windows 消息的方法。调用 Run 以启动当前线程上的应用程序消息循环,并可以选择使某窗体可见。调用 Exit 或 ExitThread 来停止消息循环。当您的程序在某个循环中时,调用 DoEvents 来处理消息。调用 AddMessageFilter 以向应用程序消息泵添加消息筛选器来监视 Windows 消息。IMessageFilter 使您可以阻止引发某事件或在调用某事件处理程序前执行特殊操作。

既然分析到了CassiniForm,我们来看看这个继承自Form的类。

阅读代码我们看到:

除了一些GUI元素支持成员变量外,还有几个成员私有变量:

     private static String _appPath;      //用于存储asp.net启动的应用程序物理路径

     private static String _portString;       //web server监听端口号

     private static String _virtRoot;      //应用程序的虚拟目录

 

private Cassini.Server _server;  // the web server 源代码中的注释

CassiniForm的构造函数也没有什么特别,我们看到有一个关键的Start(),从名字我们大致可以猜到是web server启动过程。仔细来看看:

private void Start()

{

            _appPath = appDirTextBox.Text;

            if (_appPath.Length == 0 || !Directory.Exists(_appPath)) {

                ShowError("Invalid Application Directory");

                appDirTextBox.SelectAll();

                appDirTextBox.Focus();

                return;

            }

 

            _portString = portTextBox.Text;

            int portNumber = -1;

            try {

                portNumber = Int32.Parse(_portString);

            }

            catch {

            }

            if (portNumber <= 0) {

                ShowError("Invalid Port");

                portTextBox.SelectAll();

                portTextBox.Focus();

                return;

            }

 

            _virtRoot = vrootTextBox.Text;

            if (_virtRoot.Length == 0 || !_virtRoot.StartsWith("/")) {

                ShowError("Invalid Virtual Root");

                vrootTextBox.SelectAll();

                vrootTextBox.Focus();

                return;

            }

                     //以上一大段都是检验参数,看看用户输入的参数是否符合要求。从这里我们也已看看软件的容错性多么重要,国外的程序员大都很重视,值得我借鉴。关键的实现在于下面的两行代码

            try {

                _server = new Cassini.Server(portNumber, _virtRoot, _appPath);

                _server.Start();

}

//我们可以知道在此,我们先生new一个Cassini.Server然后调用Start过程。出错了就报告错误。源代码中并没有catch(Exception e)的语句,是我为了察看错误提示信息加上去的。通过这样做,我知道编译后的程序如何执行。

            catch (Exception e){

                            MessageBox.Show(e.ToString()); 

                ShowError(

                    "Cassini Managed Web Server failed to start listening on port " + portNumber + ".\r\n" +

                    "Possible conflict with another Web Server on the same port.");

                portTextBox.SelectAll();

                portTextBox.Focus();

                return;

            }

 

            startButton.Enabled = false;

            appDirTextBox.Enabled = false;

            portTextBox.Enabled = false;

            vrootTextBox.Enabled = false;

            browseLabel.Visible = true;

            browseLink.Text = GetLinkText();

            browseLink.Visible = true;

            browseLink.Focus();

        }

CassiniForm精华差不多了。顺藤摸瓜,我们来看看Cassini.Server。这个类实际上就是我们整个Cassini的主要类。

Cassini.Server的主要数据成员有:

               private int _port;                            //端口,大概是web server的端口

        private String _virtualPath;         //虚拟目录,也就是应用程序执行的虚拟路径

        private String _physicalPath;              //物理路径

        private String _installPath;          //

 

        private WaitCallback _restartCallback;           //用于重新启动host的回调函数

        private Host _host;            //asp.net应用程序的真正宿主,从名字看J

构造函数最后调用中有:

_restartCallback = new WaitCallback(RestartCallback);              //指定一个回调函数供Restart时候使用。RestartCallback主要动作就是CreateHost()和Start(),但是需要注意是采用线程调度方式

_installPath = GetInstallPathAndConfigureAspNetIfNeeded();//这个函数搜索注册表获取 aspnet_isapi.dll的路径。该dll执行asp.net的基本框架功能(当然是在建立asp.net应用程序之后)。

CreateHost();

 

Start()很简单,就是判断hots是否存在,并且启动host,看来关于cassini.server类重点是看看CreateHost是怎么回事。

       private void CreateHost() {

            _host = (Host)ApplicationHost.CreateApplicationHost(typeof(Host), _virtualPath, _physicalPath);

            _host.Configure(this, _port, _virtualPath, _physicalPath, _installPath);

        }

原来是调用ApplicationHost的唯一方法CreateApplicationHost建立一个执行asp.net的appDomain环境。

其中的Host是一个要在新应用程序域中创建的由用户提供的类的名称。此处是一个自定义的cassini.Host,是用来承载asp.net应用程序的。

 

 

本文地址:http://com.8s8s.com/it/it42886.htm