﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客网-KiMoGiGi 技术文集</title><link>http://www.cnitblog.com/seeyeah/</link><description>不在乎选择什么，而在乎坚持多久……</description><language>zh-cn</language><lastBuildDate>Thu, 28 Aug 2008 05:09:16 GMT</lastBuildDate><pubDate>Thu, 28 Aug 2008 05:09:16 GMT</pubDate><ttl>60</ttl><item><title>HTTP协议 2</title><link>http://www.cnitblog.com/seeyeah/archive/2008/08/26/48396.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 26 Aug 2008 13:55:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/08/26/48396.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/48396.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/08/26/48396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/48396.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/48396.html</trackback:ping><description><![CDATA[<div class=postBody>引用<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/JustinYoung/articles/731369.html"><u><font color=#800080>HTTP协议</font></u></a> <br><br>众所周知，Internet的基本协议是TCP/IP协议，目前广泛采用的FTP、Archie Gopher等是建立在TCP/IP协议之上的应用层协议，不同的协议对应着不同的应用。<br>　　WWW服务器使用的主要协议是HTTP协议，即超文体传输协议。由于HTTP协议支持的服务不限于WWW，还可以是其它服务，因而HTTP协议允许用户在统一的界面下，采用不同的协议访问不同的服务，如FTP、Archie、SMTP、NNTP等。另外，HTTP协议还可用于名字服务器和分布式对象管理。<br><br>2.1　HTTP协议简介<br>　　HTTP是一个属于应用层的面向对象的协议，由于其简捷、快速的方式，适用于分布式超媒体信息系统。它于1990年提出，经过几年的使用与发展，得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版，HTTP/1.1的规范化工作正在进行之中，而且HTTP-NG(Next Generation of HTTP)的建议已经提出。<br>　　HTTP协议的主要特点可概括如下：<br>1.支持客户/服务器模式。<br>2.简单快速：客户向服务器请求服务时，只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。<br>由于HTTP协议简单，使得HTTP服务器的程序规模小，因而通信速度很快。<br>3.灵活：HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。<br>4.无连接：无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求，并收到客户的应答后，即断开连接。采用这种方式可以节省传输时间。<br>5.无状态：HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息，则它必须重传，这样可能导致每次连接传送的数据量增大。另一方面，在服务器不需要先前信息时它的应答就较快。<br><br>2.2　HTTP协议的几个重要概念<br>　　1.连接(Connection)：一个传输层的实际环流，它是建立在两个相互通讯的应用程序之间。 <br>　　2.消息(Message)：HTTP通讯的基本单位，包括一个结构化的八元组序列并通过连接传输。<br>　　3.请求(Request)：一个从客户端到服务器的请求信息包括应用于资源的方法、资源的标识符和协议的版本号<br>　　4.响应(Response)：一个从服务器返回的信息包括HTTP协议的版本号、请求的状态(例如&#8220;成功&#8221;或&#8220;没找到&#8221;)和文档的MIME类型。<br>　　5.资源(Resource)：由URI标识的网络数据对象或服务。<br>　　6.实体(Entity)：数据资源或来自服务资源的回映的一种特殊表示方法，它可能被包围在一个请求或响应信息中。一个实体包括实体头信息和实体的本身内容。<br>　　7.客户机(Client)：一个为发送请求目的而建立连接的应用程序。<br>　　8.用户代理(User agent)：初始化一个请求的客户机。它们是浏览器、编辑器或其它用户工具。<br>　　9.服务器(Server)：一个接受连接并对请求返回信息的应用程序。<br>　　10.源服务器(Origin server)：是一个给定资源可以在其上驻留或被创建的服务器。<br>　　11.代理(Proxy)：一个中间程序，它可以充当一个服务器，也可以充当一个客户机，为其它客户机建立请求。请求是通过可能的翻译在内部或经过传递到其它的服务器中。一个代理在发送请求信息之前，必须解释并且如果可能重写它。<br>　　代理经常作为通过防火墙的客户机端的门户，代理还可以作为一个帮助应用来通过协议处理没有被用户代理完成的请求。<br>　　12.网关(Gateway)：一个作为其它服务器中间媒介的服务器。与代理不同的是，网关接受请求就好象对被请求的资源来说它就是源服务器；发出请求的客户机并没有意识到它在同网关打交道。<br>　　网关经常作为通过防火墙的服务器端的门户，网关还可以作为一个协议翻译器以便存取那些存储在非HTTP系统中的资源。<br>　　13.通道(Tunnel)：是作为两个连接中继的中介程序。一旦激活，通道便被认为不属于HTTP通讯，尽管通道可能是被一个HTTP请求初始化的。当被中继的连接两端关闭时，通道便消失。当一个门户(Portal)必须存在或中介(Intermediary)不能解释中继的通讯时通道被经常使用。<br>　　14.缓存(Cache)：反应信息的局域存储。<br><br>2.3　HTTP协议的运作方式<br>　　HTTP协议是基于请求／响应范式的。一个客户机与服务器建立连接后，发送一个请求给服务器，请求方式的格式为，统一资源标识符、协议版本号，后边是MIME信息包括请求修饰符、客户机信息和可能的内容。服务器接到请求后，给予相应的响应信息，其格式为一个状态行包括信息的协议版本号、一个成功或错误的代码，后边是MIME信息包括服务器信息、实体信息和可能的内容。<br>　　许多HTTP通讯是由一个用户代理初始化的并且包括一个申请在源服务器上资源的请求。最简单的情况可能是在用户代理(UA)和源服务器(O)之间通过一个单独的连接来完成(见图2-1)。<br>图2-1<br>　　当一个或多个中介出现在请求／响应链中时，情况就变得复杂一些。中介由三种：代理(Proxy)、网关(Gateway)和通道(Tunnel)。一个代理根据URI的绝对格式来接受请求，重写全部或部分消息，通过URI的标识把已格式化过的请求发送到服务器。网关是一个接收代理，作为一些其它服务器的上层，并且如果必须的话，可以把请求翻译给下层的服务器协议。一个通道作为不改变消息的两个连接之间的中继点。当通讯需要通过一个中介(例如：防火墙等)或者是中介不能识别消息的内容时，通道经常被使用。 图2-2<br>　　上面的图2-2表明了在用户代理(UA)和源服务器(O)之间有三个中介(A,B和C)。一个通过整个链的请求或响应消息必须经过四个连接段。这个区别是重要的，因为一些HTTP通讯选择可能应用于最近的连接、没有通道的邻居，应用于链的终点或应用于沿链的所有连接。尽管图2-2是线性的，每个参与者都可能从事多重的、并发的通讯。例如，B可能从许多客户机接收请求而不通过A，并且／或者不通过C把请求送到A，在同时它还可能处理A的请求。<br>　　任何针对不作为通道的汇聚可能为处理请求启用一个内部缓存。缓存的效果是请求／响应链被缩短，条件是沿链的参与者之一具有一个缓存的响应作用于那个请求。下图说明结果链，其条件是针对一个未被UA或A加缓存的请求，B有一个经过C来自O的一个前期响应的缓存拷贝。<br>图2-3<br>　　在Internet上，HTTP通讯通常发生在TCP/IP连接之上。缺省端口是TCP 80，但其它的端口也是可用的。但这并不预示着HTTP协议在Internet或其它网络的其它协议之上才能完成。HTTP只预示着一个可靠的传输。<br>　　以上简要介绍了HTTP协议的宏观运作方式，下面介绍一下HTTP协议的内部操作过程。<br>　　首先，简单介绍基于HTTP协议的客户/服务器模式的信息交换过程，如图2-4所示，它分四个过程，建立连接、发送请求信息、发送响应信息、关闭连接。<br>图2-4<br>　　在WWW中，&#8220;客户&#8221;与&#8220;服务器&#8221;是一个相对的概念，只存在于一个特定的连接期间，即在某个连接中的客户在另一个连接中可能作为服务器。WWW服务器运行时，一直在TCP80端口(WWW的缺省端口)监听，等待连接的出现。<br>　　下面，讨论HTTP协议下客户/服务器模式中信息交换的实现。 　　1.建立连接 　　连接的建立是通过申请套接字(Socket)实现的。客户打开一个套接字并把它约束在一个端口上，如果成功，就相当于建立了一个虚拟文件。以后就可以在该虚拟文件上写数据并通过网络向外传送。<br>　　2.发送请求<br>　　打开一个连接后，客户机把请求消息送到服务器的停留端口上，完成提出请求动作。<br>　　HTTP/1.0　　请求消息的格式为：<br>　　请求消息=请求行(通用信息|请求头|实体头) CRLF[实体内容]<br>　　请求　行=方法　请求URL　HTTP版本号　CRLF<br>　　方　　法=GET|HEAD|POST|扩展方法<br>　　U　R 　L=协议名称+宿主名+目录与文件名<br>　　请求行中的方法描述指定资源中应该执行的动作，常用的方法有GET、HEAD和POST。不同的请求对象对应GET的结果是不同的，对应关系如下：<br>　　对象　　　　　　GET的结果<br>　　文件　　　　　　文件的内容<br>　　程序　　　　　　该程序的执行结果<br>　　数据库查询　　　查询结果<br>　　HEAD——要求服务器查找某对象的元信息，而不是对象本身。<br>　　POST——从客户机向服务器传送数据，在要求服务器和CGI做进一步处理时会用到POST方法。POST主要用于发送HTML文本中FORM的内容，让CGI程序处理。<br>　　一个请求的例子为：<br>　　GET http://networking.zju.edu.cn/zju/index.htm HTTP/1.0<br>　　头信息又称为元信息，即信息的信息，利用元信息可以实现有条件的请求或应答 。<br>　　请求头——告诉服务器怎样解释本次请求，主要包括用户可以接受的数据类型、压缩方法和语言等。<br>　　实体头——实体信息类型、长度、压缩方法、最后一次修改时间、数据有效期等。<br>　　实体——请求或应答对象本身。<br>　　3.发送响应<br>　　服务器在处理完客户的请求之后，要向客户机发送响应消息。<br>　　HTTP/1.0的响应消息格式如下：<br>　　响应消息=状态行(通用信息头|响应头|实体头)　CRLF　〔实体内容〕<br>　　状 态 行=HTTP版本号　状态码　原因叙述<br>　　状态码表示响应类型<br>　　1&#215;&#215;　　保留<br>　　2&#215;&#215;　　表示请求成功地接收<br>　　3&#215;&#215;　　为完成请求客户需进一步细化请求<br>　　4&#215;&#215;　　客户错误<br>　　5&#215;&#215;　　服务器错误 <br>　　响应头的信息包括：服务程序名，通知客户请求的URL需要认证，请求的资源何时能使用。<br>　　4.关闭连接<br>　　客户和服务器双方都可以通过关闭套接字来结束TCP/IP对话 </div>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/48396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-08-26 21:55 <a href="http://www.cnitblog.com/seeyeah/archive/2008/08/26/48396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTP协议</title><link>http://www.cnitblog.com/seeyeah/archive/2008/08/26/48395.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 26 Aug 2008 13:53:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/08/26/48395.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/48395.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/08/26/48395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/48395.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/48395.html</trackback:ping><description><![CDATA[<p><a href="http://www.teachblog.net/tangzz/archive/2006/11/30/3458.html#25"><u><font color=#800080></font></u></a>&nbsp;</p>
<h2 class=title1>HTTP协议简介</h2>
<h3 class=title2><a name=11></a>HTTP协议简介</h3>
<p align=left>在TCP/IP体系结构中，HTTP属于应用层协议，位于TCP/IP协议的顶层。浏览Web时，浏览器通过HTTP协议与Web服务器交换信息。这些信息（文档）类型的格式由MIME定义。</p>
<p align=left>HTTP协议具有以下的特点： </p>
<ol>
    <li>HTTP按客户/服务器模式工作<br>HTTP支持客户（一般情况是浏览器）与服务器的通讯，相互传输数据。<br>HTTP定义的事务处理由以下四步组成：
    <ul>
        <li>客户与服务器建立连接；
        <li>客户向服务器提出请求；
        <li>如果请求被接受，则服务器送回响应，在响应中包括状态码和所需的文件；
        <li>客户与服务器断开连接 </li>
    </ul>
    <table width="75%">
        <tbody>
            <tr bgColor=#ccccff>
                <td bgColor=#ccccff><em>一次HTTP操作称为一次<font color=#ff0000>事务</font>（<font color=#0000ff>transaction</font>）。</em></td>
            </tr>
        </tbody>
    </table>
    <li>HTTP是无状态的<br>也就是说，浏览器和服务器每进行一次HTTP操作，就建立一次连接，但任务结束就中断连接。
    <li>HTTP使用元信息作为头标<br>HTTP对所有事务都加了<font color=#ff0000>头标</font>（<font color=#0000ff>header</font>）。也就是说，在主要数据前加上一块信息，称为<font color=#ff0000>元信息</font>（<font color=#0000ff>metainformation</font>）。它使服务器能够提供正在传送数据的有关信息。例如，传送对象是哪种类型，是用哪种语言书写的等。<br>从功能上讲，HTTP支持四类元信息：一般信息头标、请求头标、响应头标和实体头标。
    <li>HTTP支持两种请求和响应格式<br>HTTP由不同的两部分组成，一是从浏览器发往服务器的请求，二是服务器对客户的响应。<br>HTTP支持两种请求和响应，即简单请求与完全请求和简单响应与完全响应。
    <li>HTTP是基于文本的简单协议 </li>
</ol>
<h3 class=title2><a name=12></a>HTTP的请求 </h3>
<p>HTTP的常用请求方法：</p>
<table width="85%" border=1>
    <tbody>
        <tr>
            <td width="32%"><strong>方 法</strong> </td>
            <td width="68%"><strong>说 明</strong> </td>
        </tr>
        <tr>
            <td width="32%">GET</td>
            <td width="68%">请求读取一个Web页面</td>
        </tr>
        <tr>
            <td width="32%">HEAD</td>
            <td width="68%">请求读取一个Web页面的头标</td>
        </tr>
        <tr>
            <td width="32%">PUT</td>
            <td width="68%">请求存储一个Web页面</td>
        </tr>
        <tr>
            <td width="32%">POST</td>
            <td width="68%">附加到命名资源中</td>
        </tr>
        <tr>
            <td width="32%">DELETE</td>
            <td width="68%">删除Web页面</td>
        </tr>
        <tr>
            <td width="32%">LINK</td>
            <td width="68%">连接两个已有资源</td>
        </tr>
        <tr>
            <td width="32%">UNLINK</td>
            <td width="68%">取消两个资源之间的已有连接</td>
        </tr>
    </tbody>
</table>
<p>HTTP请求的格式如下所示：</p>
<div class=code>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #000000">＜request-line＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜headers＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜blank&nbsp;line＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>[＜request-body＞]</span> </div>
</div>
<p>在HTTP请求中，第一行必须是一个请求行（request line），用来说明请求类型、要访问的资源以及使用的HTTP版本。紧接着是一个首部（header）小节，用来说明服务器要使用的附加信息。在首部之后是一个空行，再此之后可以添加任意的其他数据[称之为主体（body）]。<br>在HTTP中，定义了大量的请求类型，不过Ajax开发人员关心的只有GET请求和POST请求。只要在Web浏览器上输入一个URL，浏览器就将基于该URL向服务器发送一个GET请求，以告诉服务器获取并返回什么资源。对于<a href="http://www.wzu.edu.cn/"><u><font color=#0000ff>www.wzu.edu.cn</font></u></a>的GET请求如下所示：</p>
<div class=code>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #000000">GET&nbsp;/&nbsp;HTTP/1.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Host:&nbsp;www.wzu.edu.cn&nbsp;<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>User-Agent:&nbsp;Mozilla/5.0&nbsp;(Windows;&nbsp;U;&nbsp;Windows&nbsp;NT&nbsp;5.1;&nbsp;en-US;&nbsp;rv:1.7.6)<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Gecko/20050225&nbsp;Firefox/1.0.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Connection:&nbsp;Keep-Alive&nbsp;</span> </div>
</div>
<p>请求行的第一部分说明了该请求是GET请求。该行的第二部分是一个斜杠（/），用来说明请求的是该域名的根目录。该行的最后一部分说明使用的是HTTP 1.1版本（另一个可选项是1.0）。那么请求发到哪里去呢？这就是第二行的内容。<br>第2行是请求的第一个首部，HOST。首部HOST将指出请求的目的地。结合HOST和上一行中的斜杠（/），可以通知服务器请求的是www.wzu.edu.cn/（HTTP 1.1才需要使用首部HOST，而原来的1.0版本则不需要使用）。第三行中包含的是首部User-Agent，服务器端和客户端脚本都能够访问它，它是浏览器类型检测逻辑的重要基础。该信息由你使用的浏览器来定义（在本例中是Firefox 1.0.1），并且在每个请求中将自动发送。最后一行是首部Connection，通常将浏览器操作设置为Keep-Alive（当然也可以设置为其他值，但这已经超出了本书讨论的范围）。注意，在最后一个首部之后有一个空行。即使不存在请求主体，这个空行也是必需的。</p>
<p>如果要获取一个诸如http://www.wzu.edu.cn/books的www.wzu.edu.cn域内的页面，那么该请求可能类似于：<br></p>
<div class=code>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #000000">GET&nbsp;/books/&nbsp;HTTP/1.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Host:&nbsp;www.wzu.edu.cn<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>User-Agent:&nbsp;Mozilla/5.0&nbsp;(Windows;&nbsp;U;&nbsp;Windows&nbsp;NT&nbsp;5.1;&nbsp;en-US;&nbsp;rv:1.7.6)<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Gecko/20050225&nbsp;Firefox/1.0.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Connection:&nbsp;Keep-Alive</span> </div>
</div>
<p>注意只有第一行的内容发生了变化，它只包含URL中www.wzu.edu.cn后面的部分。</p>
<p>要发送GET请求的参数，则必须将这些额外的信息附在URL本身的后面。其格式类似于：<br></p>
<div class=code>URL ? name1=value1&amp;name2=value2&amp;..&amp;nameN=valueN</div>
<br>该信息称之为查询字符串（query string），它将会复制在HTTP请求的请求行中，如下所示：<br>
<div class=code>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">GET&nbsp;/books/?name=Professional%20Ajax&nbsp;HTTP/1.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Host:&nbsp;www.wzu.edu.cn<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>User-Agent:&nbsp;Mozilla/5.0&nbsp;(Windows;&nbsp;U;&nbsp;Windows&nbsp;NT&nbsp;5.1;&nbsp;en-US;&nbsp;rv:1.7.6)<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Gecko/20050225&nbsp;Firefox/1.0.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Connection:&nbsp;Keep-Alive</span></div>
</div>
<p>另一方面，POST请求在请求主体中为服务器提供了一些附加的信息。通常，当填写一个在线表单并提交它时，这些填入的数据将以POST请求的方式发送给服务器。</p>
<p>以下就是一个典型的POST请求：<br></p>
<div class=code>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">POST&nbsp;/&nbsp;HTTP/1.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Host:&nbsp;www.wzu.edu.cn<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>User-Agent:&nbsp;Mozilla/5.0&nbsp;(Windows;&nbsp;U;&nbsp;Windows&nbsp;NT&nbsp;5.1;&nbsp;en-US;&nbsp;rv:1.7.6)<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Gecko/20050225&nbsp;Firefox/1.0.1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Content-Type:&nbsp;application/x-www-form-urlencoded<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Content-Length:&nbsp;40<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Connection:&nbsp;Keep-Alive<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>name=Professional%20Ajax</span><span style="COLOR: #ff0000">&amp;publisher</span><span style="COLOR: #000000">=Wiley</span></div>
</div>
<p>从上面可以发现， POST请求和GET请求之间有一些区别。首先，请求行开始处的GET改为了POST，以表示不同的请求类型。你会发现首部Host和User-Agent仍然存在，在后面有两个新行。其中首部Content-Type说明了请求主体的内容是如何编码的。浏览器始终以application/ x-www-form- urlencoded的格式编码来传送数据，这是针对简单URL编码的MIME类型。首部Content-Length说明了请求主体的字节数。在首部Connection后是一个空行，再后面就是请求主体。与大多数浏览器的POST请求一样，这是以简单的&#8220;名称—值&#8221;对的形式给出的，其中name是Professional Ajax，publisher是Wiley。你可以以同样的格式来组织URL的查询字符串参数。</p>
<p>正如前面所提到的，还有其他的HTTP请求类型，它们遵从的基本格式与GET请求和POST请求相同。下一步我们来看看服务器将对HTTP请求发送什么响应。</p>
<h3>HTTP响应</h3>
<p>如下所示，HTTP响应的格式与请求的格式十分类似：<br></p>
<div class=code>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">＜status-line＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜headers＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜blank&nbsp;line＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>[＜response-body＞]</span></div>
</div>
<p>正如你所见，在响应中唯一真正的区别在于第一行中用状态信息代替了请求信息。状态行（status line）通过提供一个状态码来说明所请求的资源情况。以下就是一个HTTP响应的例子： <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">HTTP/1.1&nbsp;200&nbsp;OK<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Date:&nbsp;Sat,&nbsp;31&nbsp;Dec&nbsp;2005&nbsp;23:59:59&nbsp;GMT<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Content-Type:&nbsp;text/html;charset=ISO-8859-1<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>Content-Length:&nbsp;122<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜html＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜head＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜title＞Wrox&nbsp;Homepage＜/title＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜/head＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜body＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜!--&nbsp;body&nbsp;goes&nbsp;here&nbsp;--＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜/body＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>＜/html＞<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br></p>
<p>在本例中，状态行给出的HTTP状态代码是200，以及消息OK。状态行始终包含的是状态码和相应的简短消息，以避免混乱。最常用的状态码有：</p>
<ul>
    <li>200 (OK): 找到了该资源，并且一切正常。
    <li>304 (NOT MODIFIED): 该资源在上次请求之后没有任何修改。这通常用于浏览器的缓存机制。
    <li>401 (UNAUTHORIZED):<strong></strong>客户端无权访问该资源。这通常会使得浏览器要求用户输入用户名和密码，以登录到服务器。
    <li>403 (FORBIDDEN):<strong></strong>客户端未能获得授权。这通常是在401之后输入了不正确的用户名或密码。
    <li>404 (NOT FOUND):<strong></strong>在指定的位置不存在所申请的资源。 </li>
</ul>
<p>在状态行之后是一些首部。通常，服务器会返回一个名为Date的首部，用来说明响应生成的日期和时间（服务器通常还会返回一些关于其自身的信息，尽管并非是必需的）。接下来的两个首部大家应该熟悉，就是与POST请求中一样的Content-Type和Content-Length。在本例中，首部Content-Type指定了MIME类型HTML（text/html），其编码类型是ISO-8859-1（这是针对美国英语资源的编码标准）。响应主体所包含的就是所请求资源的HTML源文件（尽管还可能包含纯文本或其他资源类型的二进制数据）。浏览器将把这些数据显示给用户。<br>注意，这里并没有指明针对该响应的请求类型，不过这对于服务器并不重要。客户端知道每种类型的请求将返回什么类型的数据，并决定如何使用这些数据。 </p>
<h2 class=title1>与HTTP相关类的简介</h2>
<h3 class=title2><a name=21></a>WebRequest类</h3>
<p><strong>WebRequest</strong> 是 .NET Framework 的用于访问 Internet 数据的请求/响应模型的抽象基类。使用该请求/响应模型的应用程序可以用协议不可知的方式从 Internet 请求数据。在这种方式下，应用程序处理 <strong>WebRequest</strong> 类的实例，而协议特定的子类则执行请求的具体细节。</p>
<p>请求从应用程序发送到某个特定的 URI，如服务器上的 Web 页。URI 从一个为应用程序注册的 <strong>WebRequest</strong> 子代列表中确定要创建的适当子类。注册 <strong>WebRequest</strong> 子代通常是为了处理某个特定的协议（如 HTTP 或 FTP），但是也可以注册它以处理对特定服务器或服务器上的路径的请求。</p>
<p>由于 <strong>WebRequest</strong> 类是一个抽象类，所以 <strong>WebRequest</strong> 实例在运行时的实际行为由 <a href="file:///D:/Documents/教学工作/C%23网络编程/课件/frlrfsystemnetwebrequestclasscreatetopic.htm"><u><font color=#0000ff>WebRequest.Create</font></u></a> 方法所返回的子类确定。</p>
<p><span class=emphtitle><strong class=le><font color=#ff0000>注意 </font></strong></span><span class=emph><em><font color=#0000ff>使用 <strong>Create</strong> 方法初始化新的 <strong>WebRequest</strong> 实例。不要使用 <strong>WebRequest</strong> 构造函数。</font></em></span></p>
<p>下面的示例说明如何创建 <strong>WebRequest</strong> 实例并返回响应。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Initialize&nbsp;the&nbsp;WebRequest.</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">WebRequest&nbsp;myRequest&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WebRequest.Create(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://www.contoso.com</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Return&nbsp;the&nbsp;response.&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">WebResponse&nbsp;myResponse&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;myRequest.GetResponse();<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Code&nbsp;to&nbsp;use&nbsp;the&nbsp;WebResponse&nbsp;goes&nbsp;here.<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Close&nbsp;the&nbsp;response&nbsp;to&nbsp;free&nbsp;resources.</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">myResponse.Close();</span></div>
<h3>WebResponse类</h3>
<p><strong>WebResponse</strong> 类是抽象（在 Visual Basic 中为 <strong>MustInherit</strong>）基类，协议特定的响应类从该抽象基类派生。应用程序可以使用 <strong>WebResponse</strong> 类的实例以协议不可知的方式参与请求和响应事务，而从 <strong>WebResponse</strong> 派生的协议特定的类携带请求的详细信息。</p>
<p>客户端应用程序不直接创建 <strong>WebResponse</strong> 对象，而是通过调用 <a href="file:///D:/Documents/教学工作/C%23网络编程/课件/frlrfsystemnetwebrequestclasstopic.htm"><u><font color=#0000ff>WebRequest</font></u></a> 实例上的 <a href="file:///D:/Documents/教学工作/C%23网络编程/课件/frlrfsystemnetwebrequestclassgetresponsetopic.htm"><u><font color=#0000ff>GetResponse</font></u></a> 方法来创建它。</p>
<p>下面的示例从 WebRequest 创建 WebResponse 实例。 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Initialize&nbsp;the&nbsp;WebRequest.</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">WebRequest&nbsp;myRequest&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WebRequest.Create(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://www.contoso.com</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Return&nbsp;the&nbsp;response.&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">WebResponse&nbsp;myResponse&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;myRequest.GetResponse();<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Code&nbsp;to&nbsp;use&nbsp;the&nbsp;WebResponse&nbsp;goes&nbsp;here.<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Close&nbsp;the&nbsp;response&nbsp;to&nbsp;free&nbsp;resources.</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">myResponse.Close();</span></div>
<h3>HttpWebRequest类</h3>
<p><strong>HttpWebRequest</strong> 类对 <a href="http://www.teachblog.net/tangzz/archive/2006/11/30/3458.html#21"><u><font color=#800080>WebRequest</font></u></a> 中定义的属性和方法提供支持，也对使用户能够直接与使用 HTTP 的服务器交互的附加属性和方法提供支持。</p>
<p>不要使用 <a href="http://www.teachblog.net/tangzz/archive/2006/11/30/3458.html#23"><u><font color=#800080>HttpWebRequest</font></u></a> 构造函数。使用 <span class=emph><em><font color=#0000ff>WebRequest.Create</font></em></span> 方法初始化 <strong>HttpWebRequest</strong> 的一个新实例。如果 URI 的方案是 <code class=ce>http://</code> 或 <code class=ce>https://</code>，则 <strong>Create</strong> 将返回 <strong>HttpWebRequest</strong> 实例。</p>
<p><strong>GetResponse</strong> 方法向 <strong>RequestUri</strong> 属性中指定的 Internet 资源发出同步请求并返回包含该响应的 <a href="http://www.teachblog.net/tangzz/archive/2006/11/30/3458.html#24"><u><font color=#800080>HttpWebResponse</font></u></a> 实例。可以使用 <strong>BeginGetResponse</strong> 和 <strong>EndGetResponse</strong> 方法对 Internet 资源发出异步请求。</p>
<p>当要向 Internet 资源发送数据时，<strong>GetRequestStream</strong> 方法返回用于发送数据的Stream实例。<strong>BeginGetRequestStream</strong> 和 <strong>EndGetRequestStream</strong> 方法提供对发送数据流的异步访问。</p>
<p style="DISPLAY: block">下面的示例为 URI http://www.contoso.com/ 创建 <strong>HttpWebRequest</strong>。</p>
<pre class=code style="DISPLAY: block">
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">HttpWebRequest&nbsp;myReq&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(HttpWebRequest)WebRequest.Create(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://www.contoso.com/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span></div>
</pre>
<h3><a name=24></a>HttpWebResponse类</h3>
<p>此类包含对 <a href="http://www.teachblog.net/tangzz/archive/2006/11/30/3458.html#22"><u><font color=#800080>WebResponse</font></u></a> 类中的属性和方法的 HTTP 特定用法的支持。<strong>HttpWebResponse</strong> 类用于生成发送 HTTP 请求和接收 HTTP 响应的 HTTP 独立客户端应用程序。</p>
<p><span class=emphtitle><strong><font color=#ff0000>注意：</font></strong></span><span class=emph><em><font color=#0000ff>不要混淆 <strong>HttpWebResponse</strong> 和 <strong>HttpResponse</strong>；后者用于 ASP.NET 应用程序，而且它的方法和属性是通过 ASP.NET 的内部 <strong>HttpResponse</strong> 对象公开的。</font></em></span></p>
<p>决不要直接创建 <strong>HttpWebResponse</strong> 类的实例。而应当使用通过调用 <span class=emph><em><font color=#0000ff>HttpWebRequest.GetResponse</font></em></span> 所返回的实例。</p>
<p>从 Internet 资源返回的公共标头信息公开为该类的属性。有关完整的列表，请参见下表。可以从 <a href="file:///D:/Documents/教学工作/C%23网络编程/课件/frlrfsystemnethttpwebresponseclassheaderstopic.htm"><u><font color=#0000ff>Headers</font></u></a> 属性以名称/值对的形式读取其他标头。</p>
<p>下表显示可以通过 <strong>HttpWebResponse</strong> 类的属性使用的公共 HTTP 标头。</p>
<div class=tablediv>
<table class=dtTABLE cellSpacing=0 width=600 border=1>
    <tbody>
        <tr vAlign=top>
            <th width="50%">标头</th>
            <th width="50%">属性</th>
        </tr>
        <tr vAlign=top>
            <td width="50%">
            <div align=center>Content-Encoding</div>
            </td>
            <td width="50%">
            <div align=center>ContentEncoding </div>
            </td>
        </tr>
        <tr vAlign=top>
            <td width="50%">
            <div align=center>Content-Length</div>
            </td>
            <td width="50%">
            <div align=center>ContentLength </div>
            </td>
        </tr>
        <tr vAlign=top>
            <td width="50%">
            <div align=center>Content-Type</div>
            </td>
            <td width="50%">
            <div align=center>ContentType </div>
            </td>
        </tr>
        <tr vAlign=top>
            <td width="50%">
            <div align=center>Last-Modified</div>
            </td>
            <td width="50%">
            <div align=center>LastModified </div>
            </td>
        </tr>
        <tr vAlign=top>
            <td width="50%">
            <div align=center>服务器</div>
            </td>
            <td width="50%">
            <div align=center>Server </div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>通过调用 <strong>GetResponseStream</strong> 方法，以 <strong>Stream</strong> 的形式返回来自 Internet 资源的响应的内容。</p>
<p style="DISPLAY: block">下面的示例返回 <a href="file:///D:/Documents/教学工作/C%23网络编程/课件/frlrfsystemnethttpwebrequestclasstopic.htm"><u><font color=#0000ff>HttpWebRequest</font></u></a> 的 <strong>HttpWebResponse</strong>：</p>
<pre class=code style="DISPLAY: block">
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">HttpWebRequest&nbsp;HttpWReq&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(HttpWebRequest)WebRequest.Create(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://www.contoso.com</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>HttpWebResponse&nbsp;HttpWResp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(HttpWebResponse)HttpWReq.GetResponse();<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Insert&nbsp;code&nbsp;that&nbsp;uses&nbsp;the&nbsp;response&nbsp;object.</span><span style="COLOR: #008000"><br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">HttpWResp.Close()</span></div>
</pre>
<h3><a name=25></a><span class=title2>Uri类</span></h3>
<p>URI 是 Internet 上可由应用程序使用的资源的简洁表示形式。<strong>Uri</strong> 类定义了属性和方法来处理 URI，包括分析、比较和组合。<strong>Uri</strong> 类属性是只读的，修改 <strong>Uri</strong> 实例需使用 <strong>UriBuilder</strong> 类。</p>
<p><strong>Uri</strong> 类只存储绝对 URI（例如&#8220;http://www.contoso.com/index.htm&#8221;）。相对 URI（例如&#8220;/new/index.htm&#8221;）必须相对于基 URI 展开，这样才是绝对的。提供了 <strong>MakeRelative</strong> 方法在必要时将绝对 URI 转换为相对 URI。</p>
<p>URI 由转义编码存储为规范化 URI，所有 ASCII 值大于 127 的字符都被替换为它们的等效十六进制数。为使 URI 具有规范化格式，<strong>Uri</strong> 构造函数执行以下步骤。</p>
<ul type=disc>
    <li>将 URI 方案转换为小写。
    <li>将主机名转换为小写。
    <li>移除默认端口号和空端口号。
    <li>移除多余的段（如&#8220;/&#8221;和&#8220;/test&#8221;段）以简化 URI。 </li>
</ul>
<p>使用 <strong>ToString</strong> 方法，可以将 <strong>Uri</strong> 类的内容从转义编码的 URI 引用转换为可读的 URI 引用。</p>
<p>一些 URI 包括段标识符或查询。段标识符是 URI 中跟在数字符号 (#) 后的任何文本，存储在 <a href="file:///D:/Documents/教学工作/C%23网络编程/课件/frlrfsystemuriclassfragmenttopic.htm"><u><font color=#0000ff>Fragment</font></u></a> 属性中。查询信息是 URI 中跟在问号 (?) 后的任何文本，存储在 <strong>Query</strong> 属性中。</p>
<p><strong class=emphtitle><font color=#ff0000>注意：</font></strong><span class=emph><em><font color=#0000ff>URI 类支持使用以下格式的 IP 地址：四组表示法的 IPv4 协议和冒号分隔的十六进制 IPv6 协议。请记住在 IPv6 地址两边括上方括号，如 http://[::1]。</font></em></span></p>
<p style="DISPLAY: block">下面的示例创建 <strong>Uri</strong> 类的实例，并用它来创建 <a href="http://www.teachblog.net/tangzz/archive/2006/11/30/3458.html#21"><u><font color=#800080>WebRequest</font></u></a>。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">Uri&nbsp;siteUri&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Uri(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://www.contoso.com/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top>WebRequest&nbsp;wr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WebRequest.Create(siteUri);<br><img src="http://www.teachblog.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/48395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-08-26 21:53 <a href="http://www.cnitblog.com/seeyeah/archive/2008/08/26/48395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaScript多线程编程简介</title><link>http://www.cnitblog.com/seeyeah/archive/2008/08/14/48001.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 14 Aug 2008 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/08/14/48001.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/48001.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/08/14/48001.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/48001.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/48001.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.infoq.com/cn/articles/js_multithread">http://www.infoq.com/cn/articles/js_multithread</a><br>
<hr>
<p>虽然有越来越多的网站在应用AJAX技术进行开发，但是构建一个复杂的AJAX应用仍然是一个难题。造成这些困难的主要原因是什么呢？是与服务器的异步通信问题？还是GUI程序设计问题呢？通常这两项工作都是由桌面程序来完成的，那究竟为何开发一个可以实现同样功能的AJAX应用就这么困难呢？</p>
<h3>AJAX 开发中的难题</h3>
<p>让我们通过一个简单的例子来认识这个问题。假设你要建立一个树形结构的公告栏系统(BBS)，它可以根据用户请求与服务器进行交互，动态加载每篇文章的信息，而不是一次性从服务器载入所有文章信息。每篇文章有四个相关属性：系统中可以作为唯一标识的ID、发贴人姓名、文章内容以及包含其所有子文章ID的数组信息。首先假定有一个名为getArticle()的函数可以加载一篇文章信息。该函数接收的参数是要加载文章的ID，通过它可从服务器获取文章信息。它返回的对象包含与文章相关的四条属性：id，name，content和children。例程如下：</p>
<pre>function ( id ) {<br>     var a = getArticle(id);<br>     document.writeln(a.name + "<br>" + a.content);<br> } </pre>
<p>然而你也许会注意到，重复用同一个文章ID调用此函数，需要与服务器之间进行反复且无益的通信。想要解决这个问题，可以考虑使用函数 getArticleWithCache()，它相当于一个带有缓存能力的getArticle()。在这个例子中，getArticle()返回的数据只是作为一个全局变量被保存下来：</p>
<pre>var cache = {};<br> function getArticleWithCache ( id ) {<br>     if ( !cache[id] ) {<br>         cache[id] = getArticle(id);<br>     }<br>     return cache[id];<br> } </pre>
<p>现在已将读入的文章缓存起来，让我们再来考虑一下函数backgroundLoad()，它应用我们上面提到的缓存机制加载所有文章信息。其用途是，当读者在阅读某篇文章时，从后台预加载它所有子文章。因为文章数据是树状结构的，所以很容易写一个递归的算法来遍历树并且加载所有的文章：</p>
<pre>function backgroundLoad ( ids ) {<br>     for ( var i=0; i &lt; ids.length; i++ ) {<br>         var a = getArticleWithCache(ids[i]);<br>         backgroundLoad(a.children);<br>     }<br> } </pre>
<p>backgroundLoad ()函数接收一个ID数组作为参数，然后通过每个ID调用前面定义过的getArticldWithCache()方法，这样就把每个ID对应的文章缓存起来。之后再通过已加载文章的子文章ID数组递归调用backgroundLoad()方法，如此整个文章树就被缓存起来。</p>
<p>到目前为止，一切似乎看起来都很完美。然而，只要你有过开发AJAX应用的经验，你就应该知晓这种幼稚的实现方法根本不会成功，这个例子成立的基础是默认 getArticle()用的是同步通信。可是，作为一条基本原则，JavaScript要求在与服务器进行交互时要用异步通信，因为它是单线程的。就简单性而言，把每一件事情（包括GUI事件和渲染）都放在一个线程里来处理是一个很好的程序模型，因为这样就无需再考虑线程同步这些复杂问题。另一方面，他也暴露了应用开发中的一个严重问题，单线程环境看起来对用户请求响应迅速，但是当线程忙于处理其它事情时(比如说调用getArticle())，就不能对用户的鼠标点击和键盘操作做出响应。 </p>
<p>如果在这个单线程环境里进行同步通信会发生什么事情呢？同步通信会中断浏览器的执行直至获得通信结果。在等待通信结果的过程中，由于服务器的调用还没有完成，线程会停止响应用户并保持锁定状态直到调用返回。因为这个原因，当浏览器在等待服务器响应时它不能对用户行为作出响应，所以看起来像是冻结了。当执行 getArticleWithCache()和backgroundLoad()会有同样的问题，因为它们都是基于getArticle()函数的。由于下载所有的文章可能会耗费很可观的一段时间，因此对于backgroundLoad()函数来说，浏览器在此段时间内的冻结就是一个很严重的问题——既然浏览器都已经冻结，当用户正在阅读文章时就不可能首先去执行后台预加载数据，如果这样做连当前的文章都没办法读。</p>
<p>如上所述，既然同步通信在使用中会造成如此严重的问题，JavaScript就把异步通信作为一条基本原则。因此，我们可以基于异步通信改写上面的程序。 JavaScript要求以一种事件驱动的程序设计方式来写异步通信程序。在很多场合中，你都必须指定一个回调程序，一旦收到通信响应，这个函数就会被调用。例如，上面定义的getArticleWithCache()可以写成这样：</p>
<pre>var cache = {};<br> function getArticleWithCache ( id, callback ) {<br>     if ( !cache[id] ) {<br>         callback(cache[id]);<br>     } else {<br>         getArticle(id, function( a ){<br>             cache[id] = a;<br>             callback(a);<br>         });<br>     }<br> } </pre>
<p>这个程序也在内部调用了getArticle()函数。然而需要注意的是，为异步通信设计的这版getArticle()函数要接收一个函数作为第二个参数。当调用这个getArticle()函数时，与从前一样要给服务器发送一个请求，不同的是，现在函数会迅速返回而非等待服务器的响应。这意味着，当执行权交回给调用程序时，还没有得到服务器的响应。如此一来，线程就可以去执行其它任务直至获得服务器响应，并在此时调用回调函数。一旦得到服务器响应， getArticle()的第二个参数作为预先定义的回调函数就要被调用，服务器的返回值即为其参数。同样的，getArticleWithCache ()也要做些改变，定义一个回调参数作为其第二个参数。这个回调函数将在被传给getArticle()的回调函数中调用，因而它可以在服务器通信结束后被执行。</p>
<p>单是上面这些改动你可能已经认为相当复杂了，但是对backgroundLoad()函数做得改动将会更复杂，它也要被改写成可以处理回调函数的形式：</p>
<pre>function backgroundLoad ( ids, callback ) {<br>     var i = 0;<br>     function l ( ) {<br>         if ( i &lt; ids.length ) {<br>             getArticleWithCache(ids[i++], function( a ){<br>                 backgroundLoad(a.children, l);<br>             });<br>         } else {<br>             callback();<br>         }<br>     }<br>     l();<br> } </pre>
<p>改动后的backgroundLoad()函数看上去和我们以前的那个函数已经相去甚远，不过他们所实现的功能并无二致。这意味着这两个函数都接受ID数组作为参数，对于数组里的每个元素都要调用getArticleWithCache()，再应用已经获得子文章ID递归调用backgroundLoad ()。不过同样是对数组的循环访问，新函数中的就不太好辨认了，以前的程序中是用一个for循环语句完成的。为什么实现同样功能的两套函数是如此的大相径庭呢？</p>
<p>这个差异源于一个事实：任何函数在遇到有需要同服务器进行通信情况后，都必须立刻返回，例如getArticleWithCache()。除非原来的函数不在执行当中，否则应当接受服务器响应的回调函数都不能被调用。对于JavaScript，在循环过程中中断程序并在稍后从这个断点继续开始执行程序是不可能的，例如一个for语句。因此，本例利用递归传递回调函数实现循环结构而非一个传统循环语句。对那些熟悉连续传送风格(CPS)的人来说，这就是一个 CPS的手动实现，因为不能使用循环语法，所以即便如前面提到的遍历树那么简单的程序也得写得很复杂。与事件驱动程序设计相关的问题是<a href="http://www.cis.upenn.edu/~stevez/papers/LZ04a.pdf"><u><font color=#0000ff>控制流问题</font></u></a>：循环和其它控制流表达式可能比较难理解。</p>
<p>这里还有另外一个问题：如果你把一个没有应用异步通信的函数转换为一个使用异步通信的函数，那么重写的函数将需要一个回调函数作为新增参数，这为已经存在的APIs造成了很大问题，因为内在的改变没有把影响限于内部，而是导致整体混乱的APIs以及API的其它使用者的改变。</p>
<p>造成这些问题目的根本原因是什么呢？没错，正是JavaScript单线程机制导致了这些问题。在单线程里执行异步通信需要事件驱动程序设计和复杂的语句。如果当程序在等待服务器的响应时，有另外一个线程可以来处理用户请求，那么上述复杂技术就不需要了。</p>
<h3>试试多线程编程</h3>
<p>让我来介绍一下Concurrent.Thread，它是一个允许JavaScript进行多线程编程的库，应用它可以大大缓解上文提及的在AJAX开发中与异步通信相关的困难。这是一个用JavaScript写成的免费的软件库，使用它的前提是遵守Mozilla Public License和GNU General Public License这两个协议。你可以从<a href="http://jsthread.sourceforge.net/"><u><font color=#0000ff>他们的网站 </font></u></a>下载源代码。</p>
<p>马上来下载和使用源码吧！假定你已经将下载的源码保存到一个名为Concurrent.Thread.js的文件夹里，在进行任何操作之前，先运行如下程序，这是一个很简单的功能实现：</p>
<pre><code>&lt;script type="text/javascript" src="Concurrent.Thread.js"&gt;&lt;/script&gt;<br> &lt;script type="text/javascript"&gt;<br>     Concurrent.Thread.create(function(){<br>         var i = 0;<br>         while ( 1 ) {<br>             document.body.innerHTML += i++ + "&lt;br&gt;";<br>         }<br>     });<br> &lt;/script&gt;</code></pre>
<p>执行这个程序将会顺序显示从0开始的数字，它们一个接一个出现，你可以滚屏来看它。现在让我们来仔细研究一下代码，他应用while(1)条件制造了一个不会中止的循环，通常情况下，象这样不断使用一个并且是唯一一个线程的JavaScript程序会导致浏览器看起来象冻结了一样，自然也就不会允许你滚屏。那么为什么上面的这段程序允许你这么做呢？关键之处在于while(1)上面的那条Concurrent.Thread.create()语句，这是这个库提供的一个方法，它可以创建一个新线程。被当做参数传入的函数在这个新线程里执行，让我们对程序做如下微调：</p>
<pre><code>&lt;script type="text/javascript" src="Concurrent.Thread.js"&gt;&lt;/script&gt;<br> &lt;script type="text/javascript"&gt;<br>     function f ( i ){<br>         while ( 1 ) {<br>             document.body.innerHTML += i++ + "&lt;br&gt;";<br>         }<br>     }<br>     Concurrent.Thread.create(f, 0);<br>     Concurrent.Thread.create(f, 100000);<br> &lt;/script&gt; </code></pre>
<p><span style="FONT-FAMILY: monospace">在这个程序里有个新函数f()可以重复显示数字，它是在程序段起始定义的，接着以f()为参数调用了两次create()方法，传给create()方法的第二个参数将会不加修改地传给f()。执行这个程序，先会看到一些从0开始的小数，接着是一些从100,000开始的大数，然后又是接着前面小数顺序的数字。你可以观察到程序在交替显示小数和大数，这说明两个线程在同时运行。</span></p>
<p>让我来展示Concurrent.Thread的另外一个用法。上面的例子调用create()方法来创建新线程。不调用库里的任何APIs也有可能实现这个目的。例如，前面那个例子可以这样写：</p>
<pre><code>&lt;script type="text/javascript" src="Concurrent.Thread.js"&gt;&lt;/script&gt;<br> &lt;script type="text/x-script.multithreaded-js"&gt;<br>     var i = 1;<br>     while ( 1 ) {<br>         document.body.innerHTML += i++ + "&lt;br&gt;";<br>     }<br> &lt;/script&gt; </code></pre>
<p><span style="FONT-FAMILY: monospace">在script 标签内，很简单地用JavaScript写了一个无穷循环。你应该注意到标签内的type属性，那里是一个很陌生的值(text/x- script.multithreaded-js)，如果这个属性被放在script标签内，那么Concurrent.Thread就会在一个新的线程内执行标签之间的程序。你应当记住一点，在本例一样，必须将Concurrent.Thread库包含进来。</span></p>
<p>有了Concurrent.Thread，就有可能自如的将执行环境在线程之间进行切换，即使你的程序很长、连续性很强。我们可以简要地讨论下如何执行这种操作。简言之，需要进行代码转换。粗略地讲，首先要把传递给create()的函数转换成一个字符串，接着改写直至它可以被分批分次执行。然后这些程序可以依照调度程序逐步执行。调度程序负责协调多线程，换句话说，它可以在适当的时候做出调整以便每一个修改后的函数都会得到同等机会运行。 Concurrent.Thread实际上并没有创建新的线程，仅仅是在原本单线程的基础上模拟了一个多线程环境。</p>
<p>虽然转换后的函数看起来是运行在不同的线程内，但是实际上只有一个线程在做这所有的事情。在转换后的函数内执行同步通信仍然会造成浏览器冻结，你也许会认为以前的那些问题根本就没有解决。不过你不必耽心，Concurrent.Thread提供了一个应用JavaScript 的异步通信方式实现的定制通信库，它被设计成当一个线程在等待服务器的响应时允许其它线程运行。这个通信库存于 Concurrent.Thread.Http下。它的用法如下所示：</p>
<pre><code>&lt;script type="text/javascript" src="Concurrent.Thread.js"&gt;&lt;/script&gt;<br> &lt;script type="text/x-script.multithreaded-js"&gt;<br>     var req = Concurrent.Thread.Http.get(url, ["Accept", "*"]);<br>     if (req.status == 200) {<br>         alert(req.responseText);<br>     } else {<br>         alert(req.statusText);<br>     }<br> &lt;/script&gt; </code></pre>
<p>get()方法，就像它的名字暗示的那样，可以通过HTTP的GET方法获得指定URL的内容，它将目标URL作为第一个参数，将一个代表HTTP请求头的数组作为可选的第二个参数。get()方法与服务器交互，当得到服务器的响应后就返回一个XMLHttpRequest对象作为返回值。当get()方法返回时，已经收到了服务器响应，所以就没必要再用回调函数接收结果。自然，也不必再耽心当程序等待服务器的响应时浏览器冻结的情况了。另外，还有一个 post()方法可以用来发送数据到服务器：</p>
<pre><code>&lt;script type="text/javascript" src="Concurrent.Thread.js"&gt;&lt;/script&gt;<br> &lt;script type="text/x-script.multithreaded-js"&gt;<br>     var req = Concurrent.Thread.Http.post(url, "key1=val1&amp;key2=val2");<br>     alert(req.statusText);<br> &lt;/script&gt;</code> </pre>
<p>post()方法将目的URL作为第一个参数，要发送的内容作为第二个参数。像get()方法那样，你也可以将请求头作为可选的第三个参数。</p>
<p>如果你用这个通信库实现了第一个例子当中的getArticle()方法，那么你很快就能应用文章开头示例的那种简单的方法写出getArticleWithCache(),backgroundLoad ()以及其它调用了getArticle()方法的函数了。即使是那版backgroundLoad()正在读文章数据，照例还有另外一个线程可以对用户请求做出响应，浏览器因此也不会冻结。现在，你能理解在JavaScript中应用多线程有多实用了？</p>
<h3>想了解更多</h3>
<p>我向你介绍了一个可以在JavaScript中应用多线程的库：Concurrent.Thread。这篇文章的内容只是很初级的东西，如果你想更深入的了解，我推荐您去看<a href="http://jsthread.sourceforge.net/cgi-bin/wiki/wiki.cgi?page=A+Tutorial"><u><font color=#0000ff>the tutorial</font></u></a>。它提供有关Concurrent.Thread用法的更多内容，并列出了可供高级用户使用的文档，是最适合起步的材料。访问<a href="http://jsthread.sourceforge.net/"><u><font color=#0000ff>他们的网站</font></u></a>也不错，那里提供更多信息。</p>
<h3>有关作者</h3>
<p><a href="http://daisukemaki.dtdns.net/"><u><font color=#0000ff>Daisuke Maki</font></u></a>：从International Christian大学文科学院自然科学分部毕业后（取得文学学士学位），又在Electro-Communications大学的研究生院信息专业攻读硕士学位。擅长Web开发和应用JavaScript的AJAX。他开发了Concurrent.Thread。2006财政年度在日本信息技术促进机构（IPA）指导的项目Explatory Software Project中应用了这个设计。</p>
<p>目前已经拥有一个工学硕士学位的他正在Electro-Communications大学的研究生院注册攻读博士学位。</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/48001.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-08-14 23:06 <a href="http://www.cnitblog.com/seeyeah/archive/2008/08/14/48001.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Introducing Silverlight 2</title><link>http://www.cnitblog.com/seeyeah/archive/2008/08/05/47669.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 05 Aug 2008 15:08:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/08/05/47669.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/47669.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/08/05/47669.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/47669.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/47669.html</trackback:ping><description><![CDATA[<p>摘至： Essential Silverlight 2 Up-to-Date <br>
<p>
<hr>
<p>&#160;</p>
<p style="FONT-SIZE: 24pt"><strong>Part 1: Introduction</strong></p>
<p><span style="FONT-SIZE: 18pt"><strong>Chapter 1. Introducing Silverlight 2</strong></span><br><br><br>Silverlight is Microsoft's new browser-based plug-in for delivering richer interactive applications to users over the web. Silverlight 2 is Microsoft's second release of the Silverlight platform. Silverlight 2's biggest change from Silverlight 1.0 is the inclusion of a compact version of the .NET Framework, complete with the .NET Framework 3.0 Common Language Runtime. By adding .NET to Silverlight, Microsoft makes it easy for .NET developers to reuse their existing programming skills, collaborate with designers, and quickly create rich applications for the Web. </p>
<p>&nbsp;</p>
<p>And even though Silverlight 2 brings .NET to the client, it can be integrated easily with many existing Web technologies and backend Web platforms. That means Silverlight will integrate with your existing infrastructure and applications, from IIS and .NET to Apache and PHP to simple JavaScript and XHTML on the client. Silverlight is not a tool meant for exclusive use on ASP.NET web sites, which should result in broader adoption of the new technology.</p>
<p>Still, one of the key benefits of Silverlight 2 is that it can execute any .NET language, including C# and VB.NET. Unlike the CLR included with the "normal" .NET Framework, multiple instances of the core "Silverlight CLR" can be hosted in a single process. With this, the layout markup in the Silverlight XAML file (.xaml file) can be augmented by code-behind code with all programming logic written in any .NET language.</p>
<p>Silverlight 2 ships with a "lightweight" version of the full .NET Framework, which features, among other classes, extensible controls, XML Web Services, networking components, and LINQ APIs. This class library is a subset of (and is considerably smaller than) the .NET Framework's Base Class Library, which enables the Silverlight plug-in to be a fast and small download. For security, all Silverlight code runs in a sandbox environment that prevents invoking platform APIs, protecting user computers from malicious code. Silverlight 2 also adds support for DRM in media files, a fact that will make some people happy and others cringe.</p>
<p>In addition to the .NET Framework classes, Silverlight 2 also ships with a subset of the WPF UI programming model, including support for shapes, documents, media, and WPF animation objects. The Silverlight 2 December CTP did not ship with many WPF UI controls, though, so out-of-the-box controls will remain limited until beta 1. The Silverlight 2 beta 1 release promises to deliver more controls as well as the ability to bind to data. Microsoft says that the data binding limitations are strictly temporary and that future builds of Silverlight 2 will eliminate the problem. Count on future Silverlight releases to add more UI controls, data binding support, and a much needed automated layout manager to the Silverlight mix (see Figure 1-1).</p>
<p>The architecture of Silverlight 1.0 is quite complex (see <a href="http://msdn2.microsoft.com/en-us/library/bb404713.aspx">http://msdn2.microsoft.com/en-us/library/bb404713.aspx</a> for an overview), but it can be broken down into big chunks. The presentation system takes care of everything UI, including animation, text rendering, and audio/video playback. The plug-in itself integrates into the browser so that the content can be shown, as well as accessed using the JavaScript DOM. Finally, using some JavaScript code (or, optimally, the ASP.NET AJAX framework), Silverlight applications can be enriched to access server APIs such as web services. The browser plug-in then parses the markup and runs the code, even if no .NET Framework Redistributable is installed on the client. Silverlight 2 further extends this and offers a partial .NET Framework integration right into Silverlight. So you can write code in languages such as C#; this code will be compiled prior to deployment.</p>
<p align=center><br>Figure 1-1. Silverlight framework model<br>&nbsp;</p>
<p align=center><img height=658 alt="" src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/silverlightArt.JPG" width=500 border=0></p>
<p><br><strong>1.1. Rich Internet Applications</strong><br>What exactly is a "RIA" web application? And why would you want to adopt the RIA model for your own web development?</p>
<p>Rich Internet Applications, or RIAs, are web applications that have the features and functionality of traditional desktop applications. RIAs typically transfer the processing necessary for the user interface to the web client but keep the bulk of the data processing (such as maintaining the state of the program, the data, etc.) on the application server.</p>
<p>Traditional web applications implement a client/server architecture, in which a thin client (the web browser) interacts with a powerful server. Typically, all processing is done on the server and the client is used only to display static HTML content. The biggest drawback to thin-client implementations is that all interaction with the application must pass through the server. That means data must be sent to the server, the server must respond, and then the page must be reloaded on the client with the server's response. By moving more of this processing to client-side technology that can execute instructions on the client's computer, RIAs can circumvent this slow, synchronous loop for many user interactions.</p>
<p><strong>1.1.1. Benefits of Rich Internet Applications</strong><br>One of the primary benefits of RIAs is that they can offer user-interface behaviors not possible with only the HTML controls available in standard browser-based web applications. With a RIA platform, web applications are no longer limited by what the browser can do. Rather, they can implement any user interaction that the new RIA platform support, such as drag-and-drop behaviors, smooth animations, and client-side calculations. While some of these interactions are possible without a RIA platform (using Ajax, for example), the RIA approach is typically much more responsive and consistent across platforms.</p>
<p>The benefits of RIAs, however, go beyond their looks. Using a client engine can also produce other performance benefits:</p>
<p>&nbsp;</p>
<p><em>Client-server balance</em></p>
<p>RIAs shift the balance of computing resources for web applications from the server to the client. This frees up resources on the web server, enabling the same server hardware to handle more concurrent user sessions. On the flip side, the approval it requires that your users have computers that are powerful enough to execute complex client-side code, which is generally not a problem in this day and age.</p>
<p>&nbsp;</p>
<p><em>Asynchronous communication</em></p>
<p>The RIA client engine can interact with the server asynchronously—that is, without waiting for the user to perform an action such as clicking on a button or link. This feature enables RIA designers to move data between the user's PC and the server without making the user wait for the transfer to finish, similar to what Ajax provides today.</p>
<p>&nbsp;</p>
<p><em>Network efficiency</em></p>
<p>Network traffic may also be significantly reduced in a RIA because an application-specific client engine can be more intelligent than a standard web browser when deciding what data needs to be exchanged with servers. Transferring less data for each interaction can speed up individual requests and responses, in turn reducing overall network load. Use of asynchronous prefetching techniques, however, can neutralize or even reverse this potential benefit. Because code cannot anticipate exactly what every user will do next, prefetching extra data is common, not all of which is actually needed by many users.</p>
<p><strong>1.1.2. Shortcomings of Rich Internet Applications</strong><br>While RIAs offer some compelling advantages over current approaches to web development, there are a number of drawbacks that plague the technology—not the least of which are requirements of the browser plug-in itself (in most cases). Among the more serious drawbacks of RIAs are:</p>
<p>&nbsp;</p>
<p><em>Sandbox</em></p>
<p>Because RIAs run within a sandbox, they have restricted access to system resources. If users modify their systems or have reduced permissions that alter a RIA's ability to access system resources, RIAs may fail to operate correctly.</p>
<p>&nbsp;</p>
<p><em>Disabled scripting</em></p>
<p>RIAs usually require JavaScript or another scripting language to operate on the client. If the user has disabled active scripting in his browser, the RIA may not function properly, if at all.</p>
<p>&nbsp;</p>
<p><em>Script download time</em></p>
<p>Although it does not always have to be installed, the additional client-side intelligence (or client engine) of RIA applications needs to be delivered by the server to the client. While much of this is usually automatically cached, it needs to be transferred at least once. Depending on the size and type of delivery, client engine download time may be unpleasantly long, especially for users with slower Internet connections. Some RIA developers can lessen the impact of this delay by compressing scripts and by staging delivery over multiple pages of an application. For client engine s that require a plug-in to be installed, this is not an option.</p>
<p>&nbsp;</p>
<p><em>Loss of visibility to search engines</em></p>
<p>Search engines may not be able to index the text content of RIA applications. This can be a major problem for web applications that depend on search engine visibility for their success.</p>
<p>&nbsp;</p>
<p><em>Dependence on an Internet connection</em></p>
<p>While the ideal network-enabled replacement for a desktop application would allow users to be "occasionally connected," wandering in and out of hotspots or from office to office, today (in 2008) the typical RIA requires network connectivity.</p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/47669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-08-05 23:08 <a href="http://www.cnitblog.com/seeyeah/archive/2008/08/05/47669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Eclipse快捷键大全 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/30/47321.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 30 Jul 2008 15:30:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/30/47321.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/47321.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/30/47321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/47321.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/47321.html</trackback:ping><description><![CDATA[Eclipse中的快捷键 <br><br>&nbsp;&nbsp; &nbsp;本文档从Eclipse软件上整理，是列出了标准的快捷键，未列出Emacs快捷键。 <br>&nbsp;&nbsp; &nbsp;转贴请注明作者和出处。(来自Eclipse社区论坛) <br><br>&nbsp;&nbsp; &nbsp;编辑 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 查找并替换 Ctrl+F <br>&nbsp;&nbsp; &nbsp;文本编辑器 查找上一个 Ctrl+Shift+K <br>&nbsp;&nbsp; &nbsp;文本编辑器 查找下一个 Ctrl+K <br>&nbsp;&nbsp; &nbsp;全局 撤销 Ctrl+Z <br>&nbsp;&nbsp; &nbsp;全局 复制 Ctrl+C <br>&nbsp;&nbsp; &nbsp;全局 恢复上一个选择 Alt+Shift+&#8595; <br>&nbsp;&nbsp; &nbsp;全局 剪切 Ctrl+X <br>&nbsp;&nbsp; &nbsp;全局 快速修正 Ctrl1+1 <br>&nbsp;&nbsp; &nbsp;全局 内容辅助 Alt+/ <br>&nbsp;&nbsp; &nbsp;全局 全部选中 Ctrl+A <br>&nbsp;&nbsp; &nbsp;全局 删除 Delete <br>&nbsp;&nbsp; &nbsp;全局 上下文信息 Alt+？ <br><br><br>&nbsp;&nbsp; &nbsp;Java编辑器 显示工具提示描述 F2 <br>&nbsp;&nbsp; &nbsp;Java编辑器 选择封装元素 Alt+Shift+&#8593; <br>&nbsp;&nbsp; &nbsp;Java编辑器 选择上一个元素 Alt+Shift+&#8592; <br>&nbsp;&nbsp; &nbsp;Java编辑器 选择下一个元素 Alt+Shift+&#8594; <br>&nbsp;&nbsp; &nbsp;Java编辑器 <span>将选定字母全部转换成小写字母 Ctrl</span><span>+</span><span>Shift</span><span>+</span><span>Y<br></span>&nbsp;&nbsp; &nbsp;Java编辑器 <span></span><span>将选定字母全部转换成大写字母 Ctrl</span><span>+</span><span>Shift</span><span>+</span><span>X<br></span>&nbsp;&nbsp; &nbsp;Java编辑器 <span></span><span></span>在当前行之前或者之后添加空行 <span>Ctrl</span><span>+</span><span>Shift</span><span>+</span><span>Enter</span><br>&nbsp;&nbsp; &nbsp;文本编辑器 增量查找 Ctrl+J <br>&nbsp;&nbsp; &nbsp;文本编辑器 增量逆向查找 Ctrl+Shift+J <br>&nbsp;&nbsp; &nbsp;全局 粘贴 Ctrl+V <br>&nbsp;&nbsp; &nbsp;全局 重做 Ctrl+Y <br><br><br>&nbsp;&nbsp; &nbsp;查看 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 放大 Ctrl+= <br>&nbsp;&nbsp; &nbsp;全局 缩小 Ctrl+- <br><br><br>&nbsp;&nbsp; &nbsp;窗口 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 激活编辑器 F12 <br>&nbsp;&nbsp; &nbsp;全局 切换编辑器 Ctrl+Shift+W <br>&nbsp;&nbsp; &nbsp;全局 上一个编辑器 Ctrl+Shift+F6 <br>&nbsp;&nbsp; &nbsp;全局 上一个视图 Ctrl+Shift+F7 <br>&nbsp;&nbsp; &nbsp;全局 上一个透视图 Ctrl+Shift+F8 <br>&nbsp;&nbsp; &nbsp;全局 下一个编辑器 Ctrl+F6 <br>&nbsp;&nbsp; &nbsp;全局 下一个视图 Ctrl+F7 <br>&nbsp;&nbsp; &nbsp;全局 下一个透视图 Ctrl+F8 <br>&nbsp;&nbsp; &nbsp;文本编辑器 显示标尺上下文菜单 Ctrl+W <br>&nbsp;&nbsp; &nbsp;全局 显示视图菜单 Ctrl+F10 <br>&nbsp;&nbsp; &nbsp;全局 显示系统菜单 Alt+- <br><br><br>&nbsp;&nbsp; &nbsp;导航 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;Java编辑器 打开结构 Ctrl+F3 <br>&nbsp;&nbsp; &nbsp;全局 打开类型 Ctrl+Shift+T <br>&nbsp;&nbsp; &nbsp;全局 打开类型层次结构 F4 <br>&nbsp;&nbsp; &nbsp;全局 打开声明 F3 <br>&nbsp;&nbsp; &nbsp;全局 打开外部javadoc Shift+F2 <br>&nbsp;&nbsp; &nbsp;全局 打开资源 Ctrl+Shift+R <br>&nbsp;&nbsp; &nbsp;全局 后退历史记录 Alt+&#8592; <br>&nbsp;&nbsp; &nbsp;全局 前进历史记录 Alt+&#8594; <br>&nbsp;&nbsp; &nbsp;全局 上一个 Ctrl+, <br>&nbsp;&nbsp; &nbsp;全局 下一个 Ctrl+. <br>&nbsp;&nbsp; &nbsp;Java编辑器 显示大纲 Ctrl+O <br>&nbsp;&nbsp; &nbsp;全局 在层次结构中打开类型 Ctrl+Shift+H <br>&nbsp;&nbsp; &nbsp;全局 转至匹配的括号 Ctrl+Shift+P <br>&nbsp;&nbsp; &nbsp;全局 转至上一个编辑位置 Ctrl+Q <br>&nbsp;&nbsp; &nbsp;Java编辑器 转至上一个成员 Ctrl+Shift+&#8593; <br>&nbsp;&nbsp; &nbsp;Java编辑器 转至下一个成员 Ctrl+Shift+&#8595; <br>&nbsp;&nbsp; &nbsp;文本编辑器 转至行 Ctrl+L <br><br><br>&nbsp;&nbsp; &nbsp;搜索 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 出现在文件中 Ctrl+Shift+U <br>&nbsp;&nbsp; &nbsp;全局 打开搜索对话框 Ctrl+H <br>&nbsp;&nbsp; &nbsp;全局 工作区中的声明 Ctrl+G <br>&nbsp;&nbsp; &nbsp;全局 工作区中的引用 Ctrl+Shift+G <br><br><br>&nbsp;&nbsp; &nbsp;文本编辑 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;文本编辑器 改写切换 Insert <br>&nbsp;&nbsp; &nbsp;文本编辑器 上滚行 Ctrl+&#8593; <br>&nbsp;&nbsp; &nbsp;文本编辑器 下滚行 Ctrl+&#8595; <br><br><br>&nbsp;&nbsp; &nbsp;文件 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 保存 Ctrl+S <br>&nbsp;&nbsp; &nbsp;全局 打印 Ctrl+P <br>&nbsp;&nbsp; &nbsp;全局 关闭 Ctrl+F4 <br>&nbsp;&nbsp; &nbsp;全局 全部保存 Ctrl+Shift+S <br>&nbsp;&nbsp; &nbsp;全局 全部关闭 Ctrl+Shift+F4 <br>&nbsp;&nbsp; &nbsp;全局 属性 Alt+Enter <br>&nbsp;&nbsp; &nbsp;全局 新建 Ctrl+N <br><br><br>&nbsp;&nbsp; &nbsp;项目 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 全部构建 Ctrl+B <br><br><br>&nbsp;&nbsp; &nbsp;源代码 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;Java编辑器 格式化 Ctrl+Shift+F <br>&nbsp;&nbsp; &nbsp;Java编辑器 取消注释 Ctrl+\ <br>&nbsp;&nbsp; &nbsp;Java编辑器 注释 Ctrl+/ <br>&nbsp;&nbsp; &nbsp;Java编辑器 添加导入 Ctrl+Shift+M <br>&nbsp;&nbsp; &nbsp;Java编辑器 组织导入 Ctrl+Shift+O <br><br><br><br>&nbsp;&nbsp; &nbsp;运行 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 单步返回 F7 <br>&nbsp;&nbsp; &nbsp;全局 单步跳过 F6 <br>&nbsp;&nbsp; &nbsp;全局 单步跳入 F5 <br>&nbsp;&nbsp; &nbsp;全局 单步跳入选择 Ctrl+F5 <br>&nbsp;&nbsp; &nbsp;全局 调试上次启动 F11 <br>&nbsp;&nbsp; &nbsp;全局 继续 F8 <br>&nbsp;&nbsp; &nbsp;全局 使用过滤器单步执行 Shift+F5 <br>&nbsp;&nbsp; &nbsp;全局 添加/去除断点 Ctrl+Shift+B <br>&nbsp;&nbsp; &nbsp;全局 显示 Ctrl+D <br>&nbsp;&nbsp; &nbsp;全局 运行上次启动 Ctrl+F11 <br>&nbsp;&nbsp; &nbsp;全局 运行至行 Ctrl+R <br>&nbsp;&nbsp; &nbsp;全局 执行 Ctrl+U <br><br><br>&nbsp;&nbsp; &nbsp;重构 <br>&nbsp;&nbsp; &nbsp;作用域 功能 快捷键 <br>&nbsp;&nbsp; &nbsp;全局 撤销重构 Alt+Shift+Z <br>&nbsp;&nbsp; &nbsp;全局 抽取方法 Alt+Shift+M <br>&nbsp;&nbsp; &nbsp;全局 抽取局部变量 Alt+Shift+L <br>&nbsp;&nbsp; &nbsp;全局 内联 Alt+Shift+I <br>&nbsp;&nbsp; &nbsp;全局 移动 Alt+Shift+V <br>&nbsp;&nbsp; &nbsp;全局 重命名 Alt+Shift+R <br>&nbsp;&nbsp; &nbsp;全局 重做 Alt+Shift+Y <br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/47321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-30 23:30 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/30/47321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Silver Light 控件大賞</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/29/47245.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 29 Jul 2008 05:50:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/29/47245.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/47245.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/29/47245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/47245.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/47245.html</trackback:ping><description><![CDATA[<a href="http://www.silverlightnuggets.com/">http://www.silverlightnuggets.com/</a>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/47245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-29 13:50 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/29/47245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.net 页面被关闭后，服务器端是否仍然执行中？ </title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/28/47218.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 28 Jul 2008 15:37:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/28/47218.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/47218.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/28/47218.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/47218.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/47218.html</trackback:ping><description><![CDATA[摘至：<a id=ctl00_MainContent_ViewPost1_TitleUrl title="Title of this entry." href="http://blog.joycode.com/ghj/archive/2008/07/23/115199.aspx"><u><font color=#800080>ASP.net 页面被关闭后，服务器端是否仍然执行中？</font></u></a> <br>
<hr>
<p>问题：当一个正在执行中的ASPX页面执行到一半的时候，浏览器中你关闭了这个页面，服务器端对应的这个页面的代码仍然在执行么？</p>
<p>答案：除非你代码里面做了特殊判断，否则仍然正在执行。</p>
<p>&nbsp;</p>
<p><strong>注意点：</strong></p>
<p>1、客户端显示页面的时候，后台已经执行完了的页面对象早已经不存在了。当然这时候谈不上服务器段执行不执行的问题了。</p>
<p>2、页面还没有返回，处于等待状态的时候。关闭ASPX页面，才会涉及到上面提到的服务器端仍然在执行的情况。</p>
<p>3、客户端关闭的时候根本不向服务器发送指令。</p>
<p>4、除非你代码里面做了特殊判断，这里的特殊判断指用 if(!Response.IsClientConnected) 来检测状态而用代码终止运行。</p>
<p>下面的简单代码就是演示关闭页面后，看是否仍然在执行？</p>
<p>你可以在这个页面打开后， 还没有返回任何信息的时候把这个页面关闭，然后看指定目录下是否有对应文件被创建并填写内容。</p>
<pre>        <span style="COLOR: #0000ff">protected</span> <span style="COLOR: #0000ff">void</span> Page_Load(<span style="COLOR: #0000ff">object</span> sender, EventArgs e)
{
StringBuilder txt = <span style="COLOR: #0000ff">new</span> StringBuilder();
txt.AppendLine();
txt.AppendLine(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
txt.AppendLine("<span style="COLOR: #8b0000">asvd</span>");
Response.Write(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write("<span style="COLOR: #8b0000">&lt;br /&gt;\r\n</span>");
Thread.Sleep(50000);
txt.AppendLine(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write("<span style="COLOR: #8b0000">&lt;br /&gt;\r\n</span>");
<span style="COLOR: #008000">// 把一些信息写到另外一个文件,借此察看是否正在运行</span>
<span style="COLOR: #0000ff">string</span> dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "<span style="COLOR: #8b0000">logs</span>");
<span style="COLOR: #0000ff">if</span> (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
DateTime dt = DateTime.Now;
<span style="COLOR: #0000ff">string</span> shortfileName = <span style="COLOR: #0000ff">string</span>.Format("<span style="COLOR: #8b0000">errors_{0:0000}{1:00}{2:00}.log</span>", dt.Year, dt.Month, dt.Day);
<span style="COLOR: #0000ff">string</span> fileName = Path.Combine(dir, shortfileName);
StreamWriter sw;
<span style="COLOR: #0000ff">if</span> (File.Exists(fileName))
sw = File.AppendText(fileName);
<span style="COLOR: #0000ff">else</span>
sw = File.CreateText(fileName);
sw.Write(txt.ToString());
sw.Close();
sw = <span style="COLOR: #0000ff">null</span>;
}</pre>
<p>&nbsp;</p>
<p>作了特殊判断的情况简单例子：</p>
<p>注意： IsClientConnected 的判断在 VS.net 开发工具自带的开发站点 ASP.NET Development Server&nbsp; 是不支持的。 ASP.NET Development Server 永远返回 true 。</p>
<p>IIS 才是支持的。</p>
<pre>        <span style="COLOR: #0000ff">protected</span> <span style="COLOR: #0000ff">void</span> Page_Load(<span style="COLOR: #0000ff">object</span> sender, EventArgs e)
{
StringBuilder txt = <span style="COLOR: #0000ff">new</span> StringBuilder();
<span style="COLOR: #0000ff">for</span> (<span style="COLOR: #0000ff">int</span> i = 0; i &lt; 100; i++)
{
<span style="COLOR: #0000ff">if</span> (<span style="COLOR: #0000ff">this</span>.Response.IsClientConnected)
{
txt.AppendLine();
txt.AppendLine(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
txt.AppendLine(i.ToString());
Response.Write(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write("<span style="COLOR: #8b0000">&lt;br /&gt;\r\n</span>");
Thread.Sleep(500);
}
<span style="COLOR: #0000ff">else</span>
{
Response.End();
<span style="COLOR: #0000ff">return</span>;
}
}
txt.AppendLine(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write("<span style="COLOR: #8b0000">&lt;br /&gt;\r\n</span>");
<span style="COLOR: #008000">// 把一些信息写到另外一个文件,借此察看是否正在运行</span>
<span style="COLOR: #0000ff">string</span> dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "<span style="COLOR: #8b0000">logs</span>");
<span style="COLOR: #0000ff">if</span> (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
DateTime dt = DateTime.Now;
<span style="COLOR: #0000ff">string</span> shortfileName = <span style="COLOR: #0000ff">string</span>.Format("<span style="COLOR: #8b0000">errors_{0:0000}{1:00}{2:00}.log</span>", dt.Year, dt.Month, dt.Day);
<span style="COLOR: #0000ff">string</span> fileName = Path.Combine(dir, shortfileName);
StreamWriter sw;
<span style="COLOR: #0000ff">if</span> (File.Exists(fileName))
sw = File.AppendText(fileName);
<span style="COLOR: #0000ff">else</span>
sw = File.CreateText(fileName);
sw.Write(txt.ToString());
sw.Close();
sw = <span style="COLOR: #0000ff">null</span>;
}</pre>
<p>这个例子中是发现中断，就抛弃之前做的任何东西。</p>
<p>当然我们也可以简单的修改上述代码，让把已经处理完成的东西记录下来，类似下面的代码</p>
<pre>        <span style="COLOR: #0000ff">protected</span> <span style="COLOR: #0000ff">void</span> Page_Load(<span style="COLOR: #0000ff">object</span> sender, EventArgs e)
{
StringBuilder txt = <span style="COLOR: #0000ff">new</span> StringBuilder();
<span style="COLOR: #0000ff">for</span> (<span style="COLOR: #0000ff">int</span> i = 0; i &lt; 100; i++)
{
<span style="COLOR: #0000ff">if</span> (<span style="COLOR: #0000ff">this</span>.Response.IsClientConnected)
{
txt.AppendLine();
txt.AppendLine(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
txt.Append("<span style="COLOR: #8b0000">**********  </span>");
txt.AppendLine(i.ToString());
Response.Write(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write("<span style="COLOR: #8b0000">&lt;br /&gt;\r\n</span>");
Thread.Sleep(500);
}
<span style="COLOR: #0000ff">else</span>
{
<span style="COLOR: #0000ff">break</span>;
}
}
txt.AppendLine(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write(DateTime.Now.ToString("<span style="COLOR: #8b0000">u</span>"));
Response.Write("<span style="COLOR: #8b0000">&lt;br /&gt;\r\n</span>");
<span style="COLOR: #008000">// 把一些信息写到另外一个文件,借此察看是否正在运行</span>
<span style="COLOR: #0000ff">string</span> dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "<span style="COLOR: #8b0000">logs</span>");
<span style="COLOR: #0000ff">if</span> (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
DateTime dt = DateTime.Now;
<span style="COLOR: #0000ff">string</span> shortfileName = <span style="COLOR: #0000ff">string</span>.Format("<span style="COLOR: #8b0000">errors_{0:0000}{1:00}{2:00}.log</span>", dt.Year, dt.Month, dt.Day);
<span style="COLOR: #0000ff">string</span> fileName = Path.Combine(dir, shortfileName);
StreamWriter sw;
<span style="COLOR: #0000ff">if</span> (File.Exists(fileName))
sw = File.AppendText(fileName);
<span style="COLOR: #0000ff">else</span>
sw = File.CreateText(fileName);
sw.Write(txt.ToString());
sw.Close();
sw = <span style="COLOR: #0000ff">null</span>;
}</pre>
<p>需要注意的是， 使用 isClientConnected&nbsp;&nbsp; 是要占用一定的系统资源的。 </p>
<p>isClientConnected&nbsp;&nbsp; 实际上需要向客户端输出一点东西，然后才知道客户端是否仍然在线。</p>
<p>这样，除非你的应用非常耗时，否则建议你不要用 isClientConnected&nbsp;&nbsp; 。 免得判断 isClientConnected&nbsp;&nbsp; 使用的资源比你实际业务逻辑使用的资源还要多。</p>
<p>在任何情况下， Response.IsClientConnected 都要有些开销，所以，只有在执行至少要用 500 毫秒（如果想维持每秒几十页的吞吐量，这是一个很长的时间了）的操作前才使用它。作为通常的规则，不要在紧密循环的每次迭代中调用它，例如当绘制表中的行，可能每&nbsp; 20 行或每 50 行调用一次。 </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>参考资料：</strong></p>
<p>how to increase timeout on aspx page? <br><a title=http://p2p.wrox.com/topic.asp?TOPIC_ID=7504 href="http://p2p.wrox.com/topic.asp?TOPIC_ID=7504"><u><font color=#0000ff>http://p2p.wrox.com/topic.asp?TOPIC_ID=7504</font></u></a></p>
<p>asp.net能不能在客户端关闭后在后台继续将页面执行完毕？ <br><a title=http://topic.csdn.net/u/20070202/14/85ea5576-907a-4960-9c53-b206a05228e4.html href="http://topic.csdn.net/u/20070202/14/85ea5576-907a-4960-9c53-b206a05228e4.html"><u><font color=#0000ff>http://topic.csdn.net/u/20070202/14/85ea5576-907a-4960-9c53-b206a05228e4.html</font></u></a></p>
<p>在 ASP.NET 中使用计时器（Timer） <br><a title=http://blog.joycode.com/percyboy/articles/3595.aspx href="http://blog.joycode.com/percyboy/articles/3595.aspx"><u><font color=#0000ff>http://blog.joycode.com/percyboy/articles/3595.aspx</font></u></a></p>
<p>ASP.NET 2.0 中的异步页 <br><a title=http://www.microsoft.com/china/msdn/library/webservices/asp.net/issuesWickedCodetoc.mspx?mfr=true href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/issuesWickedCodetoc.mspx?mfr=true"><u><font color=#0000ff>http://www.microsoft.com/china/msdn/library/webservices/asp.net/issuesWickedCodetoc.mspx?mfr=true</font></u></a></p>
<p>IsClientConnected的问题 <br><a title=http://topic.csdn.net/u/20080712/19/74fa4070-84bd-4fda-a99b-ac361f874738.html href="http://topic.csdn.net/u/20080712/19/74fa4070-84bd-4fda-a99b-ac361f874738.html"><u><font color=#0000ff>http://topic.csdn.net/u/20080712/19/74fa4070-84bd-4fda-a99b-ac361f874738.html</font></u></a></p>
<p>Response.IsClientConnected 原理和用法 <br><a title=http://blog.51ait.cn/article.asp?id=357 href="http://blog.51ait.cn/article.asp?id=357"><u><font color=#0000ff>http://blog.51ait.cn/article.asp?id=357</font></u></a>&nbsp;&nbsp;&nbsp; 第一个地址比较慢，可以看下一个地址 <br><a title=http://blog.joycode.com/ghj/archive/2008/07/23/115198.aspx href="http://blog.joycode.com/ghj/archive/2008/07/23/115198.aspx"><u><font color=#0000ff>http://blog.joycode.com/ghj/archive/2008/07/23/115198.aspx</font></u></a></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/47218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-28 23:37 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/28/47218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IIS5、IIS6、IIS7的ASP.net 请求处理过程比较 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/28/47217.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 28 Jul 2008 15:36:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/28/47217.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/47217.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/28/47217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/47217.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/47217.html</trackback:ping><description><![CDATA[摘至：<a id=ctl00_MainContent_ViewPost1_TitleUrl title="Title of this entry." href="http://blog.joycode.com/ghj/archive/2008/07/25/115200.aspx"><u><font color=#800080>IIS5、IIS6、IIS7的ASP.net 请求处理过程比较</font></u></a> <br>
<hr>
<p>ASP.NET是一个非常强大的构建Web应用的平台，它提供了极大的灵活性和能力以致于可以用它来构建所有类型的Web应用。 <br>绝大多数的人只熟悉高层的框架如： WebForms 和 WebServices --这些都在ASP.NET层次结构在最高层。</p>
<p>这篇文章的资料收集整理自各种微软公开的文档，通过比较 IIS5、IIS6、IIS7 这三代 IIS 对请求的处理过程， 让我们熟悉 ASP.NET的底层机制 并对请求(request)是怎么从Web服务器传送到ASP.NET运行时有所了解。通过对底层机制的了解，可以让我们对 ASP.net 有更深的理解。</p>
<p><strong>IIS 5 的 ASP.net 请求处理过程</strong></p>
<p><img src="http://blog.joycode.com/images/blog.joycode.com/ghj/1362/o_8001.gif"></p>
<p>对图的解释：</p>
<p>IIS 5.x 一个显著的特征就是 Web Server 和真正的 ASP.NET Application 的分离。作为 Web Server 的IIS运行在一个名为 InetInfo.exe 的进程上，InetInfo.exe 是一个Native Executive，并不是一个托管的程序，而我们真正的 ASP.NET Application 则是运行在一个叫做 aspnet_wp 的 Worker Process 上面，在该进程初始化的时候会加载CLR，所以这是一个托管的环境。</p>
<p>ISAPI：&nbsp; 指能够处理各种后缀名的应用程序。 ISAPI 是下面单词的简写 ：Internet Server Application Programe Interface，互联网服务器应用程序接口。</p>
<p>IIS 5 模式的特点：</p>
<p>1、首先，同一台主机上在同一时间只能运行一个 aspnet_wp 进程，每个基于虚拟目录的 ASP.NET Application 对应一个 Application Domain ，也就是说每个 Application 都运行在同一个 Worker Process 中，Application之间的隔离是基于 Application Domain 的，而不是基于Process的。 </p>
<p>2、其次，ASP.NET&nbsp; ISAPI 不但负责创建 aspnet_wp Worker Process，而且负责监控该进程，如果检测到 aspnet_wp 的 Performance 降低到某个设定的下限，ASP.NET&nbsp; ISAPI 会负责结束掉该进程。当 aspnet_wp 结束掉之后，后续的 Request 会导致ASP.NET ISAPI 重新创建新的 aspnet_wp Worker Process。 </p>
<p>3、最后，由于 IIS 和 Application 运行在他们各自的进程中，他们之间的通信必须采用特定的通信机制。本质上 IIS 所在的 InetInfo 进程和 Worker Process 之间的通信是同一台机器不同进程的通信（local interprocess communications），处于Performance的考虑，他们之间采用基于Named pipe的通信机制。ASP.NET ISAPI和Worker Process之间的通信通过他们之间的一组Pipe实现。同样处于Performance的原因，ASP.NET ISAPI 通过异步的方式将Request 传到Worker Process 并获得 Response，但是 Worker Process 则是通过同步的方式向 ASP.NET ISAPI 获得一些基于 Server 的变量。 </p>
<p>&nbsp;</p>
<p><strong>IIS6 的 ASP.net 请求处理过程</strong></p>
<p><img src="http://blog.joycode.com/images/blog.joycode.com/ghj/1362/o_8002.gif"></p>
<p>对图的解释：</p>
<p>IIS 5.x 是通过 InetInfo.exe 监听 Request 并把Request分发到Work Process。换句话说，在IIS 5.x中对Request的监听和分发是在User Mode中进行，在IIS 6中，这种工作被移植到kernel Mode中进行，所有的这一切都是通过一个新的组件：http.sys 来负责。 </p>
<p>注：为了避免用户应用程序访问或者修改关键的操作系统数据，windows提供了两种处理器访问模式：用户模式（User Mode）和内核模式（Kernel Mode）。一般地，用户程序运行在User mode下，而操作系统代码运行在Kernel Mode下。Kernel Mode的代码允许访问所有系统内存和所有CPU指令。</p>
<p>在User Mode下，http.sys接收到一个基于 aspx 的http request，然后它会根据IIS中的 Metabase 查看该基于该 Request 的 Application 属于哪个Application Pool， 如果该Application Pool不存在，则创建之。否则直接将 request 发到对应Application Pool 的 Queue中。</p>
<p>每个 Application Pool 对应着一个Worker Process：w3wp.exe，毫无疑问他是运行在User Mode下的。在IIS Metabase 中维护着 Application Pool 和worker process的Mapping。WAS（Web Administrative service）根据这样一个mapping，将存在于某个Application Pool Queue的request 传递到对应的worker process(如果没有，就创建这样一个进程)。在 worker process 初始化的时候，加载ASP.NET ISAPI，ASP.NET ISAPI 进而加载CLR。最后的流程就和IIS 5.x一样了：通过AppManagerAppDomainFactory 的 Create方法为 Application 创建一个Application Domain；通过 ISAPIRuntime 的 ProcessRequest处理Request，进而将流程进入到ASP.NET Http Runtime Pipeline。</p>
<p>&nbsp;</p>
<p><strong>IIS 7&nbsp; 的 ASP.net 请求处理过程</strong></p>
<p>&nbsp;</p>
<p>IIS7 站点启动并处理请求的步骤如下图：</p>
<p>步骤 1 到 6 ，是处理应用启动，启动好后，以后就不需要再走这个步骤了。</p>
<p><img height=617 src="http://blog.joycode.com/images/blog.joycode.com/ghj/1362/o_9010.jpg" width=690></p>
<p>上图的8个步骤分别如下：</p>
<p>1、当客户端浏览器开始HTTP 请求一个WEB 服务器的资源时，HTTP.sys 拦截到这个请求。 <br>2、HTTP.sys contacts WAS to obtain information from the configuration store. </p>
<p>3、WAS 向配置存储中心请求配置信息。applicationHost.config。 <br>4、WWW 服务接受到配置信息，配置信息指类似应用程序池配置信息，站点配置信息等等。 <br>5、WWW 服务使用配置信息去配置 HTTP.sys 处理策略。 <br>6、WAS starts a worker process for the application pool to which the request was made. </p>
<p>7、The worker process processes the request and returns a response to HTTP.sys. </p>
<p>8、客户端接受到处理结果信息。</p>
<p>W3WP.exe 进程中又是如果处理得呢？？ IIS 7 的应用程序池的托管管道模式分两种： 经典和集成。 这两种模式下处理策略各不相通。</p>
<p><font color=#ffffff>本文作者：郭红俊</font> <a title=http://blog.joycode.com/ghj href="http://blog.joycode.com/ghj"><font color=#ffffff><u>http://blog.joycode.com/ghj</u></font></a></p>
<p>&nbsp;</p>
<p><strong>IIS 6 以及 IIS7 经典模式的托管管道的架构</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在IIS7之前，ASP.NET 是以 IIS ISAPI extension 的方式外加到 IIS，其实包括 ASP 以及 PHP，也都以相同的方式配置（PHP 在 IIS 采用了两种配置方式，除了 IIS ISAPI extension 的方式，也包括了 CGI 的方式，系统管理者能选择 PHP 程序的执行方式），因此客户端对 IIS 的 HTTP 请求会先经由 IIS 处理，然后 IIS 根据要求的内容类型，如果是 HTML 静态网页就由 IIS 自行处理，如果不是，就根据要求的内容类型，分派给各自的 IIS ISAPI extension；如果要求的内容类型是 ASP.NET，就分派给负责处理 ASP.NET 的 IIS ISAPI extension，也就是 aspnet_isapi.dll。下图是这个架构的示意图。 </p>
<p>IIS&nbsp; 7 应用程序池的 托管管道模式&nbsp; 经典&nbsp; 模式也是这样的工作原理。 这种模式是兼容IIS 6 的方式， 以减少升级的成本。</p>
<p><img src="http://blog.joycode.com/images/blog.joycode.com/ghj/1362/o_9003.jpg"></p>
<p>IIS6 的执行架构图，以及 IIS7&nbsp; 应用程序池配置成经典模式的执行架构图</p>
<p>&nbsp;</p>
<p><strong>IIS&nbsp; 7 应用程序池的 托管管道模式&nbsp; 集成模式</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而 IIS 7 完全整合 .NET 之后，架构的处理顺序有了很大的不同（如下图），最主要的原因就是 ASP.NET 从 IIS 插件（ISAPI extension）的角色，进入了 IIS 核心，而且也能以 ASP.NET 模块负责处理 IIS 7 的诸多类型要求。这些 ASP.NET 模块不只能处理 ASP.NET 网页程序，也能处理其他如 ASP 程序、PHP 程序或静态 HTML 网页，也因为 ASP.NET 的诸多功能已经成为 IIS 7 的一部份，因此 ASP 程序、PHP 程序或静态 HTML 网页等类型的要求，也能使用像是Forms认证（Forms Authentication）或输出缓存（Output Cache）等 ASP.NET 2.0 的功能（但须修改 IIS 7 的设定值）。也因为 IIS 7 允许自行以 ASP.NET API 开发并加入模块，因此 ASP.NET 网页开发人员将更容易扩充 IIS 7 和网站应用程序的功能，甚至能自行以 .NET 编写管理 IIS 7 的程序（例如以程控 IIS 7 以建置网站或虚拟目录）。</p>
<p><img src="http://blog.joycode.com/images/blog.joycode.com/ghj/1362/o_9004.jpg"></p>
<p>IIS 7 的执行架构图（集成托管信道模式下的架构）</p>
<p>&nbsp;</p>
<p><strong>小结</strong></p>
<p>IIS5 到 IIS6 的改进，主要是 HTTP.sys 的改进。</p>
<p>IIS6 到 IIS7 的改进，主要是 ISAPI 的改进。</p>
<p>&#160;</p>
<p>&nbsp;</p>
<p><strong>参考资料：</strong></p>
<p>ASP.NET Process Model之一：IIS 和 ASP.NET ISAPI <br><a title=http://www.cnblogs.com/artech/archive/2007/09/09/887528.html href="http://www.cnblogs.com/artech/archive/2007/09/09/887528.html"><u><font color=#0000ff>http://www.cnblogs.com/artech/archive/2007/09/09/887528.html</font></u></a></p>
<p>ASP.NET Internals &#8211; IIS and the Process Model <br><a title=http://dotnetslackers.com/articles/iis/ASPNETInternalsIISAndTheProcessModel.aspx href="http://dotnetslackers.com/articles/iis/ASPNETInternalsIISAndTheProcessModel.aspx"><u><font color=#0000ff>http://dotnetslackers.com/articles/iis/ASPNETInternalsIISAndTheProcessModel.aspx</font></u></a></p>
<p>模组化的IIS 7 与.NET 能力整合 <br><a title=http://www.microsoft.com/taiwan/technet/columns/profwin/33-iis7-componentization-integration.mspx href="http://www.microsoft.com/taiwan/technet/columns/profwin/33-iis7-componentization-integration.mspx"><u><font color=#0000ff>http://www.microsoft.com/taiwan/technet/columns/profwin/33-iis7-componentization-integration.mspx</font></u></a></p>
<p>Introduction to IIS 7.0 Architecture <br><a title=http://learn.iis.net/page.aspx/101/introduction-to-iis7-architecture/ href="http://learn.iis.net/page.aspx/101/introduction-to-iis7-architecture/"><u><font color=#0000ff>http://learn.iis.net/page.aspx/101/introduction-to-iis7-architecture/</font></u></a></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/47217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-28 23:36 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/28/47217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Wiki发展相关文章</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/17/46852.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 17 Jul 2008 14:17:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/17/46852.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/46852.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/17/46852.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/46852.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/46852.html</trackback:ping><description><![CDATA[1、<a title="成长速度难以乐观 中文Wiki路在何方" href="http://news.21tx.com/2006/08/31/10735.html" target=_blank>成长速度难以乐观 中文Wiki路在何方</a><br><br>2、<a title="Wiki中国发展探路：不要总拿百科说事 " href="http://oss.lzu.edu.cn/blog/article.php?tid_419.html">Wiki中国发展探路：不要总拿百科说事 </a><br><br>3、<a title="国内Wiki发展的现状与趋势探析 " href="http://dev2all.blog.51cto.com/73116/11053" target=_blank>国内Wiki发展的现状与趋势探析 </a><br><br>4、<a title=如何大灶知识型的Wiki社群 href="http://internet.chinaitlab.com/meet/532080.html" target=_blank>如何大灶知识型的Wiki社群</a><br><br>5、<a title=Wiki的商业化之道 href="http://bbs.vsharing.com/Article.aspx?aid=433679" target=_blank>Wiki的商业化之道</a> <br><br>6、<a title=百度知道到底有什么用? href="http://zhidao.baidu.com/question/34549727.html?si=5&amp;wtp=wk">百度知道到底有什么用?</a>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/46852.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-17 22:17 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/17/46852.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.Net Remoting Reference</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 15 Jul 2008 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/46760.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/46760.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/46760.html</trackback:ping><description><![CDATA[<p><a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/wayfarer/"><u><font color=#0000ff>张逸:晴窗笔记</font></u></a><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html"><u><font color=#800080>Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇 </font></u></a><br><br><a id=viewpost1_TitleUrl href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html"><font color=#000080><u>Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务</u></font></a></p>
<p><a id=viewpost1_TitleUrl href="http://www.cnblogs.com/wayfarer/articles/75213.html"><font color=#000080><u>Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触</u></font></a><br><br>
<hr>
<p><a class=HeaderMainTitle id=Header1_HeaderTitle href="http://www.cnblogs.com/dahuaidan410/"><u><font color=#0000ff>大坏蛋</font></u></a><br><br><a id=CategoryEntryList1_EntryStoryList_Entries_ctl01_TitleUrl href="http://www.cnblogs.com/dahuaidan410/archive/2004/08/09/31658.html"><u><font color=#0000ff>.NET Remoting中的事件处理(.NET Framework 2.0) </font></u></a><br><br><a id=CategoryEntryList1_EntryStoryList_Entries_ctl00_TitleUrl href="http://www.cnblogs.com/dahuaidan410/archive/2004/09/10/41726.html"><u><font color=#0000ff>.NET Remoting的新特性-IpcChannel(.NET Framework 2.0) </font></u></a><br><br>
<hr>
<br><a href="http://www.cnblogs.com/zhenyulu/"><font color=#0000ff><u>吕震宇</u></font></a><font color=#0000ff><u> </u></font><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/zhenyulu/articles/29357.html"><u><font color=#800080>利用Event松耦合远程对象与远程系统</font></u></a>
<p>&nbsp;</p>
<hr>
<br><a class=HeaderMainTitle id=Header1_HeaderTitle href="http://www.cnblogs.com/Ansel/"><u><font color=#0000ff>Ansel's Blog</font></u></a><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/Ansel/archive/2005/04/19/140595.html"><u><font color=#800080>WebService VS .NET Remoting</font></u></a> <br><br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/46760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-15 23:06 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Quick Start Guide to iBATIS DataMapper</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 10 Jul 2008 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/46575.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/46575.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/46575.html</trackback:ping><description><![CDATA[<h3><a name=QuickStartGuide-Overview></a>Overview</h3>
<p>iBATIS DataMapper is a Java/.NET framework that will help you design and implement better persistence layers for your Java/.NET applications. iBATIS couples objects with stored procedures or SQL statements using a XML descriptor. Simplicity is the biggest advantage of the iBATIS Data Mapper over object relational mapping tools. </p>
<p>To use iBATIS Data Mapper you rely on your own objects, XML, and SQL. There is little to learn that you don't already know. With iBATIS Data Mapper you have the full power of both SQL and stored procedures at your fingertips.</p>
<h3><a name=QuickStartGuide-Oursampleproject></a>Our sample project</h3>
<p>This sample takes an "over-the-shoulder" Cookbook approach. We'll define a simple data access problem and use iBATIS to solve it for us. Let's say our client has a database and one of the tables in the database is a list of people. The client tells us:</p>
<p>"We would like to use a web application to display the people in this table and to add, edit, and delete individual records."</p>
<p>Not a complicated story, but it will cover the CRUD most developers want to learn first. <img class=emoticon height=20 alt="" src="http://opensource.atlassian.com/confluence/oss/images/icons/emoticons/smile.gif" width=20 align=absMiddle border=0> </p>
<h3><a name=QuickStartGuide-Step1%3ATheSQL></a>Step 1 : The SQL</h3>
<p>Let's start with the people table client mentioned. Since we're keeping it simple, we'll say it's a table in an Access database. The table definition is shown as </p>
<table class=confluenceTable>
    <tbody>
        <tr>
            <th class=confluenceTh>Name</th>
            <th class=confluenceTh>Type</th>
            <th class=confluenceTh>Size</th>
        </tr>
        <tr>
            <td class=confluenceTd>PER_ID</td>
            <td class=confluenceTd>Long Integer</td>
            <td class=confluenceTd>4</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_FIRST_NAME</td>
            <td class=confluenceTd>Text</td>
            <td class=confluenceTd>40</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_LAST_NAME </td>
            <td class=confluenceTd>Text</td>
            <td class=confluenceTd>40</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_BIRTH_DATE </td>
            <td class=confluenceTd>Date/Time</td>
            <td class=confluenceTd>8</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_WEIGHT_KG </td>
            <td class=confluenceTd>Double</td>
            <td class=confluenceTd>8</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_HEIGHT_M </td>
            <td class=confluenceTd>Double</td>
            <td class=confluenceTd>8</td>
        </tr>
    </tbody>
</table>
<h3><a name=QuickStartGuide-Step2%3AThe.NETClass></a>Step 2 :The.NET Class</h3>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>Person.cs</strong></div>
<div class=codeContent>
<pre class=code-java>using <span class=code-object>System</span>;
namespace iBatisTutorial.Model
{
<span class=code-keyword>public</span> class Person
{
<span class=code-keyword>private</span> <span class=code-object>int</span> _id;
<span class=code-keyword>private</span> string _firstName;
<span class=code-keyword>private</span> string _lastName;
<span class=code-keyword>private</span> DateTime _birthDate;
<span class=code-keyword>private</span> <span class=code-object>double</span> _weightInKilograms;
<span class=code-keyword>private</span> <span class=code-object>double</span> _heightInMeters;
<span class=code-keyword>public</span> <span class=code-object>int</span> Id
{
get{ <span class=code-keyword>return</span> _id; }
set{ _id = value; }
}
<span class=code-comment>// Other <span class=code-keyword>public</span> properties <span class=code-keyword>for</span> the <span class=code-keyword>private</span> fields ...
</span>
}
}</pre>
</div>
</div>
<h3><a name=QuickStartGuide-Step3%3ATheNunittest></a>Step 3 :The Nunit test</h3>
<p>The first thing our story says is that client would like to display a list of people. </p>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>PersonTest.cs</strong></div>
<div class=codeContent>
<pre class=code-java>using <span class=code-object>System</span>.Collections;
using IBatisNet.DataMapper;
using NUnit.Framework;
namespace iBatisTutorial.Model
{
[TestFixture]
<span class=code-keyword>public</span> class PersonTest
{
[Test]
<span class=code-keyword>public</span> void PersonList ()
{
<span class=code-comment>// <span class=code-keyword>try</span> it
</span>    IList people = Mapper.Instance().QueryForList(<span class=code-quote>"SelectAll"</span>,<span class=code-keyword>null</span>);
<span class=code-comment>// test it
</span>    Assert.IsNotNull(people,<span class=code-quote>"Person list not returned"</span>);
Assert.IsTrue(people.Count&gt;0,<span class=code-quote>"Person list is empty"</span>);
Person person = (Person) people[0];
Assert.IsNotNull(person,<span class=code-quote>"Person not returned"</span>);
}
}
}</pre>
</div>
</div>
<p>OK, that was fun! The Assert class is built into NUnit, so to compile, we just need the Mapper object and QueryForList method. The Mapper is built into the iBATIS framework, so we don't need to write that either. The iBATIS <strong>QueryForList</strong> method executes our SQL statement (or stored procedure) and returns the result as a list. <br>Each row in the result becomes an entry in the list. Along with QueryForList, there is also Delete, Insert, Select, QueryForObject, and a couple of other methods in the iBATIS API. (See the Developers Guide for details.)</p>
<p>Looking at <strong>PersonTest</strong> class, we see that the <strong>QueryForList</strong> method takes the name of the statement we want to run and any runtime values the statement may need. Since a "SelectAll" statement wouldn't need any runtime values, we pass null in our test.</p>
<p>OK. Easy enough. But where does iBATIS get the "<strong>SelectAll</strong>" statement? </p>
<p>Some systems try to generate SQL statements for you, but iBATIS specializes in data mapping, not code generation. It's our job (or the job of our database administrator) to craft the SQL or provide a stored procedure. We then describe the statement in an XML element, like the one shown below.</p>
<h3><a name=QuickStartGuide-Step4%3AThemappingfile></a>Step 4 :The mapping file</h3>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>Person.xml</strong></div>
<div class=codeContent>
<pre class=code-xml><span class=code-tag>&lt;alias&gt;</span>
<span class=code-tag>&lt;typeAlias alias=<span class=code-quote>"Person"</span> type=<span class=code-quote>"iBatisTutorial.Model.Person, iBatisTutorial.Model"</span> /&gt;</span>
<span class=code-tag>&lt;/alias&gt;</span>
<span class=code-tag>&lt;resultMap id=<span class=code-quote>"SelectAllResult"</span> class=<span class=code-quote>"Person"</span>&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"Id"</span> column=<span class=code-quote>"PER_ID"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"FirstName"</span> column=<span class=code-quote>"PER_FIRST_NAME"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"LastName"</span> column=<span class=code-quote>"PER_LAST_NAME"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"BirthDate"</span> column=<span class=code-quote>"PER_BIRTH_DATE"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"WeightInKilograms"</span> column=<span class=code-quote>"PER_WEIGHT_KG"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"HeightInMeters"</span> column=<span class=code-quote>"PER_HEIGHT_M"</span> /&gt;</span>
<span class=code-tag>&lt;/resultMap&gt;</span>
<span class=code-tag>&lt;select id=<span class=code-quote>"SelectAll"</span> resultMap=<span class=code-quote>"SelectAllResult"</span>&gt;</span>
select
PER_ID,
PER_FIRST_NAME,
PER_LAST_NAME,
PER_BIRTH_DATE,
PER_WEIGHT_KG,
PER_HEIGHT_M
from PERSON
<span class=code-tag>&lt;/select&gt;</span></pre>
</div>
</div>
<p>The iBATIS mapping documents can hold several sets of related elements, like those shown. We can also have as many mapping documents as we need. Having multiple mapping documents is handy when several developers are working on the project at once.</p>
<p>So, the framework gets the SQL code for the query from the mapping, and plugs it into a prepared statement. But, how does iBATIS know where to find the table's datasource?</p>
<p>Surprise! More XML! You can define a configuration file for each datasource your application uses. The example below shows a configuration file for our Access database.</p>
<h3><a name=QuickStartGuide-Step5%3ATheconfigurationfile></a>Step 5 :The configuration file</h3>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>SqlMap.Config - A configuration file for our Access database</strong></div>
<div class=codeContent>
<pre class=code-xml><span class=code-tag>&lt;?xml version=<span class=code-quote>"1.0"</span> encoding=<span class=code-quote>"UTF-8"</span> ?&gt;</span>
&lt;sqlMapConfig
xmlns=<span class=code-quote>"http://ibatis.apache.org/dataMapper"</span>
<span class=code-keyword>xmlns:xsi</span>=<span class=code-quote>"http://www.w3.org/2001/XMLSchema-instance"</span> &gt;
<span class=code-tag>&lt;database&gt;</span>
<span class=code-tag>&lt;provider name=<span class=code-quote>"OleDb1.1"</span>/&gt;</span>
&lt;dataSource name=<span class=code-quote>"iBatisTutorial"</span>
connectionString=<span class=code-quote>"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=./Resources/iBatisTutorial.mdb"</span>/&gt;
<span class=code-tag>&lt;/database&gt;</span>
<span class=code-tag>&lt;sqlMaps&gt;</span>
<span class=code-tag>&lt;sqlMap resource=<span class=code-quote>"Resources/Person.xml"</span> /&gt;</span>
<span class=code-tag>&lt;/sqlMaps&gt;</span>
<span class=code-tag>&lt;/sqlMapConfig&gt;</span></pre>
</div>
</div>
<p>Of course, besides Access, other ADO.NET providers are supported, including SqlServer, Oracle, MySQL, PostgreSQL, DB2 and generic OLEDB, ODBC providers. (See the Developers Guide for details.)</p>
<p>The last part of the configuration file ("sqlMaps") is where we list our mapping documents, like the one shown back in Step 4. We can list as many documents as we need here, and they will all be read when the configuration is parsed.</p>
<p>OK, so how does the configuration get parsed?</p>
<p>Look back at PersonTest class in step 3. The heart of the code is the call to the "Mapper" object (under the remark "try it"). The Mapper object is a singleton. The first time it's called, it reads in the configuration documents to create the Mapper object. On subsequent calls, it reuses the Mapper object, so that the configuration is re-read only if the file changes.</p>
<p>The framework comes bundled with a default Mapper class. If you want to use a different name for the configuration file, or need to use more than one database, you can also use your own class, by copying and modifying the standard version.</p>
<p>The following example shows the code for the standard Mapper class that comes with the framework.</p>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>Mapper.cs</strong></div>
<div class=codeContent>
<pre class=code-java>using IBatisNet.Common.Utilities;
using IBatisNet.DataMapper;
namespace IBatisNet.DataMapper
{
<span class=code-keyword>public</span> class Mapper
{
<span class=code-keyword>private</span> <span class=code-keyword>static</span> <span class=code-keyword>volatile</span> SqlMapper _mapper = <span class=code-keyword>null</span>;
<span class=code-keyword>protected</span> <span class=code-keyword>static</span> void Configure (object obj)
{
_mapper = (SqlMapper) obj;
}
<span class=code-keyword>protected</span> <span class=code-keyword>static</span> void InitMapper()
{
ConfigureHandler handler = <span class=code-keyword>new</span> ConfigureHandler (Configure);
_mapper = SqlMapper.ConfigureAndWatch (handler);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> SqlMapper Instance()
{
<span class=code-keyword>if</span> (_mapper == <span class=code-keyword>null</span>)
{
lock (typeof (SqlMapper))
{
<span class=code-keyword>if</span> (_mapper == <span class=code-keyword>null</span>) <span class=code-comment>// <span class=code-object>double</span>-check
</span>      InitMapper();
}
}
<span class=code-keyword>return</span> _mapper;
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> SqlMapper Get()
{
<span class=code-keyword>return</span> Instance();
}
}
}</pre>
</div>
</div>
<p>You can access as many different 