﻿<?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>博客园-DotNet笔记</title><link>http://www.cnblogs.com/tuyile006/</link><description>兴趣是最好的老师。</description><language>zh-cn</language><lastBuildDate>Wed, 10 Feb 2010 05:25:17 GMT</lastBuildDate><pubDate>Wed, 10 Feb 2010 05:25:17 GMT</pubDate><ttl>60</ttl><item><title>使用SqlDependency进行缓存</title><link>http://www.cnblogs.com/tuyile006/archive/2010/02/01/1660910.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Mon, 01 Feb 2010 04:12:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2010/02/01/1660910.html</guid><description><![CDATA[<p>阅读: 41 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2010-02-01 12:12 <a href="http://www.cnblogs.com/tuyile006/archive/2010/02/01/1660910.html" target="_blank">原文链接</a></p><p><strong><span style="color: #ff6600;">&nbsp;</span></strong></p>
<p>缓存是每个系统都必定涉及到的功能，一般的缓存有一个难题&mdash;&mdash;什么时候清除？如Asp.Net中的cache可以设置一个过期时间，但设置多久合适呢？长了浪费，短了就失去缓存的意义了。使用SqlDependency进行缓存则可以解决这个问题。</p>
<p>SqlDependency是.net2.0封装的一个类型，当然要配合sql2005或以上版本才能使用。</p>
<p>SqlDependency类需要数据库的ServiceBroker来支持，当数据库中的数据发生变化时通知应用程序更新缓存，这才是最有效的缓存方式。</p>
<p>&nbsp;</p>
<p><strong><span style="color: #ff6600;">步骤一：</span></strong></p>
<p>sql数据库必须开启ServiceBroker服务，首先检测是否已经启用ServiceBroker，检测方法：</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">Select</span><span style="color: #000000;">  DATABASEpRoPERTYEX(</span><span style="color: #ff0000;">'</span><span style="color: #ff0000;">数据库名称</span><span style="color: #ff0000;">'</span><span style="color: #000000;">,</span><span style="color: #ff0000;">'</span><span style="color: #ff0000;">IsBrokerEnabled</span><span style="color: #ff0000;">'</span><span style="color: #000000;">)<br /></span></div></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>--1表示已经启用0表示没有启用</p>
<p>&nbsp;</p>
<p><span style="color: #ff6600;"><strong>步骤二：</strong></span></p>
<p>如果ServiceBroker没有启用，使用下面语句启用：</p>
<div class="cnblogs_code">
<pre><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">ALTER</span><span style="color: #000000;">  </span><span style="color: #0000ff;">DATABASE</span><span style="color: #000000;">  </span><span style="color: #808080;">&lt;</span><span style="color: #000000;">数据库名称</span><span style="color: #808080;">&gt;</span><span style="color: #000000;">  </span><span style="color: #0000ff;">SET</span><span style="color: #000000;">  ENABLE_BROKER;<br /></span></div></pre>
</div>
<p>&nbsp;</p>
<p><span style="color: #ff6600;"><strong>步骤三：</strong></span></p>
<p>在实现基于服务的SQL数据缓存依赖过程中，需要显式调用SqlDependency.Start来启动接受依赖项更改通知的侦听器。</p>
<p>&nbsp;</p>
<div style="width: 774px; height: 115px;" class="cnblogs_code">
<pre><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">SqlDependency.Start(connectionString);</span><span style="color: #008000;">//</span><span style="color: #008000;">推荐将这段代码加到Global.asax的Application_Start方法中 </span><span style="color: #008000;"><br /></span><span style="color: #000000;">SqlDependency.Stop(connectionString);</span><span style="color: #008000;">//</span><span style="color: #008000;">用于关闭，可加在Global.asax的Application_End方法中</span><span style="color: #008000;"><br /></span></div></pre>
</div>
<p>&nbsp;</p>
<p><span style="color: #ff6600;"><strong>步骤四：缓存实现</strong></span></p>
<p>&nbsp;使用sqldependency实现缓存的代码：</p>
<p>&nbsp;</p>
<div style="width: 767px; height: 651px;" class="cnblogs_code">
<pre><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;"> </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> CacheHelper<br />    {<br />        </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> Cache WebCache </span><span style="color: #000000;">=</span><span style="color: #000000;"> HttpContext.Current.Cache;<br />        </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">string</span><span style="color: #000000;"> DefaultConn </span><span style="color: #000000;">=</span><span style="color: #000000;"> ConfigurationManager.ConnectionStrings[</span><span style="color: #800000;">"</span><span style="color: #800000;">Default</span><span style="color: #800000;">"</span><span style="color: #000000;">].ConnectionString;<br /><br />        </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> DataTable GetSystemParams()<br />        {<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (WebCache[</span><span style="color: #800000;">"</span><span style="color: #800000;">SystemParam</span><span style="color: #800000;">"</span><span style="color: #000000;">] </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />            {<br />                </span><span style="color: #0000ff;">string</span><span style="color: #000000;"> strSQL </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">select uSystemParamID,ParamName,ParamValue,Description from dbo.DTS_SystemParam</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />                SqlDataAdapter da </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> SqlDataAdapter(strSQL, DefaultConn);<br />                SqlDependency dep </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> SqlDependency(da.SelectCommand);<br />                dep.OnChange </span><span style="color: #000000;">+=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> OnChangeEventHandler(dep_OnChange);<br />                DataTable tbl </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> DataTable();<br />                da.Fill(tbl);<br />                WebCache[</span><span style="color: #800000;">"</span><span style="color: #800000;">SystemParam</span><span style="color: #800000;">"</span><span style="color: #000000;">] </span><span style="color: #000000;">=</span><span style="color: #000000;"> tbl;<br />                </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> tbl;<br />            }<br />            </span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />            {<br />                </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> (DataTable)WebCache[</span><span style="color: #800000;">"</span><span style="color: #800000;">SystemParam</span><span style="color: #800000;">"</span><span style="color: #000000;">];<br />            }<br />        }<br /><br />        </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> dep_OnChange(</span><span style="color: #0000ff;">object</span><span style="color: #000000;"> sender, SqlNotificationEventArgs e)<br />        {<br />            WebCache.Remove(</span><span style="color: #800000;">"</span><span style="color: #800000;">SystemParam</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />        }<br />    }</span></div></pre>
</div>
<p>&nbsp;</p>
<p>注意：</p>
<p><span style="font-size: 9pt; color: black; font-family: '微软雅黑','sans-serif';">使用 SqlDependency 订阅查询通知必须向SQL Server Service Broker提供制定规则的查询语句，一般来讲，必须是简单的sql查询语句（</span><span style="font-size: 9pt; color: green; font-family: '微软雅黑','sans-serif';">不能用*，不能用top，不能用函数，包括聚合函数，不能用子查询，包括where后的子查询，不能用外连接，自连接，不能用临时表，不能用变量，不能用视图，不能垮库，表名之前必须加类似dbo数据库所有者这样的前缀</span><span style="font-size: 9pt; color: black; font-family: '微软雅黑','sans-serif';">）</span><span style="font-size: 9pt; color: black; font-family: '微软雅黑','sans-serif';">例如：select * from table1，select column1 from table1，select count(*) from table1 都是错误的sql查询语句，select column1 from dbo.table1 则是正确的语句。</span></p><img src="http://www.cnblogs.com/tuyile006/aggbug/1660910.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2010/02/01/1660910.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2010/02/01/1660910.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>IE6 中的最大最小寬度和高度 css 高度 控制(兼容版本)</title><link>http://www.cnblogs.com/tuyile006/archive/2009/12/23/1631026.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Wed, 23 Dec 2009 15:21:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/12/23/1631026.html</guid><description><![CDATA[<p>阅读: 123 评论: 2 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-12-23 23:21 <a href="http://www.cnblogs.com/tuyile006/archive/2009/12/23/1631026.html" target="_blank">原文链接</a></p><pre class="highlighted css"><span class="normal"><span class="comment">/* 最小寬度 */</span><span class="function"><br />.min</span>_width<span class="function">{</span><span class="storageClass">min-width</span>:<span class="number">300px</span>;<br />  <span class="comment">/* sets max-width for IE */</span><br />  _width:expression(document.body.clientWidth &lt; <span class="number">300</span> ? <span class="string">"300px"</span> : <span class="string">"auto"</span>);<br /><span class="function">}</span><br /><br /><span class="comment">/* 最大寬度 */</span><br /><span class="function">.max</span>_width<span class="function">{</span><br />  <span class="storageClass">max-width</span>:<span class="number">600px</span>;<br />  <span class="comment">/* sets max-width for IE */</span><br />  _width:expression(document.body.clientWidth &gt; <span class="number">600</span> ? <span class="string">"600px"</span> : <span class="string">"auto"</span>);<br /><span class="function">}</span><br /><br /><span class="comment">/* 最小高度 */</span><br /><span class="function">.min</span>_height<span class="function">{</span><br />  <span class="storageClass">min-height</span>:<span class="number">200px</span>;<br />  <span class="comment">/* sets min-height for IE */</span><br />  _height:expression(this.scrollHeight &lt; <span class="number">200</span> ? <span class="string">"200px"</span> : <span class="string">"auto"</span>);<br /><span class="function">}</span><br /><br /><span class="comment">/* 最大高度 */</span><br /><span class="function">.max</span>_height<span class="function">{</span><br />  <span class="storageClass">max-height</span>:<span class="number">400px</span>;<br />  <span class="comment">/* sets max-height for IE */</span><br />  _height:expression(this.scrollHeight &gt; <span class="number">400</span> ? <span class="string">"400px"</span> : <span class="string">"auto"</span>);<br /><span class="function">}</span><br /><br /><span class="comment">/* 最大最小寬度 */</span><br /><span class="function">.min</span>_and_max_width<span class="function">{</span><br />  <span class="storageClass">min-width</span>:<span class="number">300px</span>;<br />  <span class="storageClass">max-width</span>:<span class="number">600px</span>;<br />  <span class="comment">/* sets min-width &amp; max-width for IE */</span><br />  _width: expression(<br />    document.body.clientWidth &lt; <span class="number">300</span> ? <span class="string">"300px"</span> :<br />       ( document.body.clientWidth &gt; <span class="number">600</span> ? <span class="string">"600px"</span> : <span class="string">"auto"</span>)<br />  );<br /><span class="function">}</span><br /><br /><span class="comment">/* 最大最小高度 */</span><br /><span class="function">.min</span>_and_max_height<span class="function">{</span><br />  <span class="storageClass">min-height</span>:<span class="number">200px</span>;<br />  <span class="storageClass">max-height</span>:<span class="number">400px</span>;<br />  <span class="comment">/* sets min-height &amp; max-height for IE */</span><br />  _height: expression(<br />    this.scrollHeight &lt; <span class="number">200</span> ? <span class="string">"200px"</span> :<br />      ( this.scrollHeight &gt; <span class="number">400</span> ? <span class="string">"400px"</span> : <span class="string">"auto"</span>)<br />  );<br /><span class="function">}</span></span></pre><img src="http://www.cnblogs.com/tuyile006/aggbug/1631026.html?type=1" width="1" height="1" alt=""/><p>评论: 2　<a href="http://www.cnblogs.com/tuyile006/archive/2009/12/23/1631026.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/12/23/1631026.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>IHttpModule和IHttpHandler 应用笔记</title><link>http://www.cnblogs.com/tuyile006/archive/2009/10/14/1583029.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Wed, 14 Oct 2009 02:37:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/10/14/1583029.html</guid><description><![CDATA[<p>阅读: 407 评论: 1 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-10-14 10:37 <a href="http://www.cnblogs.com/tuyile006/archive/2009/10/14/1583029.html" target="_blank">原文链接</a></p><div class="NewsContent">ASP.NET 提供了 IHttpHandler 和 IHttpModule 接口，它可使您使用与在 IIS 中所用的 Internet 服务器 API (ISAPI) 编程接口同样强大的 API，而且具有更简单的编程模型。HTTP 处理程序对象与 IIS ISAPI 扩展的功能相似，而 HTTP 模块对象与 IIS ISAPI 筛选器的功能相似。</div>
<div class="NewsContent">ASP.NET 将 HTTP 请求映射到 HTTP 处理程序上。每个 HTTP 处理程序都会启用应用程序内单个的 HTTP URL 处理或 URL 扩展组处理。HTTP 处理程序具有和 ISAPI 扩展相同的功能，同时具有更简单的编程模型。</div>
<div class="NewsContent">HTTP 模块是处理事件的程序集。ASP.NET 包括应用程序可使用的一组 HTTP 模块。例如，ASP.NET 提供的 SessionStateModule 向应用程序提供会话状态服务。也可以创建自定义的 HTTP 模块以响应 ASP.NET 事件或用户事件。</div>
<div class="NewsContent"><br />关于HttpModule的注册、应用方法请参看我的另一篇博文：<br /></div>
<p><a href="http://www.cnblogs.com/tuyile006/archive/2007/09/10/888208.html">使用HTTP模块扩展 ASP.NET 处理</a></p>
<p>&nbsp;</p>
<p>关于IHttpHandler的应用，我们先从它的注册方法讲起。</p>
<p>当你建立了一个实现了Ihttphandler接口的类后，可以在网站的web.config文件中注册这个httphandler</p>
<p>示例如下：</p>
<p>&nbsp;</p>
<div class="cnblogs_code"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">httpHandlers</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">remove&nbsp;</span><span style="color: #FF0000;">verb</span><span style="color: #0000FF;">="*"</span><span style="color: #FF0000;">&nbsp;path</span><span style="color: #0000FF;">="*.asmx"</span><span style="color: #0000FF;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">add&nbsp;</span><span style="color: #FF0000;">verb</span><span style="color: #0000FF;">="*"</span><span style="color: #FF0000;">&nbsp;path</span><span style="color: #0000FF;">="*.asmx"</span><span style="color: #FF0000;">&nbsp;validate</span><span style="color: #0000FF;">="false"</span><span style="color: #FF0000;">&nbsp;type</span><span style="color: #0000FF;">="System.Web.Script.Services.ScriptHandlerFactory,&nbsp;System.Web.Extensions,&nbsp;Version=3.5.0.0,&nbsp;Culture=neutral,&nbsp;PublicKeyToken=31BF3856AD364E35"</span><span style="color: #0000FF;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">add&nbsp;</span><span style="color: #FF0000;">verb</span><span style="color: #0000FF;">="*"</span><span style="color: #FF0000;">&nbsp;path</span><span style="color: #0000FF;">="*.ho"</span><span style="color: #FF0000;">&nbsp;type</span><span style="color: #0000FF;">="WebApplication2.HelloHandler,WebApplication2"</span><span style="color: #0000FF;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">httpHandlers</span><span style="color: #0000FF;">&gt;</span></div>
<p>&nbsp;</p>
<p>其中最后一行&nbsp; <span style="color: #0000FF;">&lt;</span><span style="color: #800000;">add&nbsp;</span><span style="color: #FF0000;">verb</span><span style="color: #0000FF;">="*"</span><span style="color: #FF0000;">&nbsp;path</span><span style="color: #0000FF;">="*.ho"</span><span style="color: #FF0000;">&nbsp;type</span><span style="color: #0000FF;">="WebApplication2.HelloHandler,WebApplication2"</span><span style="color: #0000FF;">/&gt;</span><span style="color: #000000;"><br />便是我们手工加入的内容，WebApplication2.HelloHandler是实现了IhttpHandler接口的一个类，Path属性表示的是映射的文件格式。</span></p>
<p><span style="color: #000000;">这样注册好之后，如果从网站请求任何带后缀名.ho的文件时，就会转到WebApplication2.HelloHandler类进行处理。</span></p>
<p><span style="color: #000000;">而WebApplication2.HelloHandler的内容可以是在网页上打印一行文本（如下面代码），也可以是下载一个文件，反正在httphandler里面你可以控制response对象的输出。</span></p>
<p><span style="color: #000000;">下面代码示例打印一行文字的WebApplication2.HelloHandler源码：</span></p>
<div class="cnblogs_code"><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Data;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Configuration;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Linq;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.Security;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI.HtmlControls;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI.WebControls;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI.WebControls.WebParts;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Xml.Linq;<br /><br /></span><span style="color: #0000FF;">namespace</span><span style="color: #000000;">&nbsp;WebApplication2<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">class</span><span style="color: #000000;">&nbsp;HelloHandler:IHttpHandler<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">#region</span><span style="color: #000000;">&nbsp;IHttpHandler</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">void</span><span style="color: #000000;">&nbsp;ProcessRequest(HttpContext&nbsp;context)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.ContentType&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">text/html</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(</span><span style="color: #800000;">"</span><span style="color: #800000;">&lt;html&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(</span><span style="color: #800000;">"</span><span style="color: #800000;">&lt;body&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(</span><span style="color: #800000;">"</span><span style="color: #800000;">&lt;b&gt;Response&nbsp;by&nbsp;HelloHandler!&lt;/B&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(</span><span style="color: #800000;">"</span><span style="color: #800000;">&lt;/body&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(</span><span style="color: #800000;">"</span><span style="color: #800000;">&lt;/html&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">bool</span><span style="color: #000000;">&nbsp;IsReusable<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">get</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;</span><span style="color: #0000FF;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">true</span><span style="color: #000000;">;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div>
<p>&nbsp;</p>
<p><span style="color: #000000;"><strong>以下内容为转载的IhttpHandler示例：</strong><span style="color: #ff0000;"><span style="color: #ff6600;">利用IhttpHandler实现文件下载</span></span></span></p>
<p><span style="color: #000000;"><span style="color: #ff0000;"></span></span>&nbsp;</p>
<p><span style="color: #000000;">1.&nbsp;首先新建一个用于下载文件的page页，如download.aspx，里面什么东西也没有。 <br /><br />2.&nbsp;添加一个DownloadHandler类，它继承于IHttpHandler接口，可以用来自定义HTTP&nbsp;处理程序同步处理HTTP的请求。 </span></p>
<p>
<div>
<div class="cnblogs_code"><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.IO;<br /></span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">class</span><span style="color: #000000;">&nbsp;DownloadHandler&nbsp;:&nbsp;IHttpHandler<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">void</span><span style="color: #000000;">&nbsp;ProcessRequest(HttpContext&nbsp;context)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpResponse&nbsp;Response&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;context.Response;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpRequest&nbsp;Request&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;context.Request;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.IO.Stream&nbsp;iStream&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">null</span><span style="color: #000000;">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[]&nbsp;buffer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">new</span><span style="color: #000000;">&nbsp;Byte[</span><span style="color: #800080;">10240</span><span style="color: #000000;">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">int</span><span style="color: #000000;">&nbsp;length;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">long</span><span style="color: #000000;">&nbsp;dataToRead;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">try</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;filename&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;FileHelper.Decrypt(Request[</span><span style="color: #800000;">"</span><span style="color: #800000;">fn</span><span style="color: #800000;">"</span><span style="color: #000000;">]);&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">通过解密得到文件名</span><span style="color: #008000;"><br /></span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;filepath&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;HttpContext.Current.Server.MapPath(</span><span style="color: #800000;">"</span><span style="color: #800000;">~/</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">files/</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;filename;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">待下载的文件路径</span><span style="color: #008000;"><br /></span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iStream&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">new</span><span style="color: #000000;">&nbsp;System.IO.FileStream(filepath,&nbsp;System.IO.FileMode.Open,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.IO.FileAccess.Read,&nbsp;System.IO.FileShare.Read);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Clear();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataToRead&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;iStream.Length;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">long</span><span style="color: #000000;">&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">if</span><span style="color: #000000;">&nbsp;(Request.Headers[</span><span style="color: #800000;">"</span><span style="color: #800000;">Range</span><span style="color: #800000;">"</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">null</span><span style="color: #000000;">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.StatusCode&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">206</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">long</span><span style="color: #000000;">.Parse(Request.Headers[</span><span style="color: #800000;">"</span><span style="color: #800000;">Range</span><span style="color: #800000;">"</span><span style="color: #000000;">].Replace(</span><span style="color: #800000;">"</span><span style="color: #800000;">bytes=</span><span style="color: #800000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #800000;">""</span><span style="color: #000000;">).Replace(</span><span style="color: #800000;">"</span><span style="color: #800000;">-</span><span style="color: #800000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #800000;">""</span><span style="color: #000000;">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">if</span><span style="color: #000000;">&nbsp;(p&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.AddHeader(</span><span style="color: #800000;">"</span><span style="color: #800000;">Content-Range</span><span style="color: #800000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">bytes&nbsp;</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;p.ToString()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">-</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;((</span><span style="color: #0000FF;">long</span><span style="color: #000000;">)&nbsp;(dataToRead&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">1</span><span style="color: #000000;">)).ToString()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">/</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dataToRead.ToString());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.AddHeader(</span><span style="color: #800000;">"</span><span style="color: #800000;">Content-Length</span><span style="color: #800000;">"</span><span style="color: #000000;">,&nbsp;((</span><span style="color: #0000FF;">long</span><span style="color: #000000;">)&nbsp;(dataToRead&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;p)).ToString());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.ContentType&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">application/octet-stream</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.AddHeader(</span><span style="color: #800000;">"</span><span style="color: #800000;">Content-Disposition</span><span style="color: #800000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">attachment;&nbsp;filename=</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;System.Web.HttpUtility.UrlEncode(System.Text.Encoding.GetEncoding(</span><span style="color: #800080;">65001</span><span style="color: #000000;">).GetBytes(Path.GetFileName(filename))));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iStream.Position&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataToRead&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;dataToRead&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;p;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">while</span><span style="color: #000000;">&nbsp;(dataToRead&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">if</span><span style="color: #000000;">&nbsp;(Response.IsClientConnected)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;length&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;iStream.Read(buffer,&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">,&nbsp;</span><span style="color: #800080;">10240</span><span style="color: #000000;">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.OutputStream.Write(buffer,&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">,&nbsp;length);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Flush();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">new</span><span style="color: #000000;">&nbsp;Byte[</span><span style="color: #800080;">10240</span><span style="color: #000000;">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataToRead&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;dataToRead&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;length;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">else</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataToRead&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #800080;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">catch</span><span style="color: #000000;">&nbsp;(Exception&nbsp;ex)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Write(</span><span style="color: #800000;">"</span><span style="color: #800000;">Error&nbsp;:&nbsp;</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;ex.Message);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">finally</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">if</span><span style="color: #000000;">&nbsp;(iStream&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">null</span><span style="color: #000000;">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iStream.Close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.End();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">bool</span><span style="color: #000000;">&nbsp;IsReusable<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">get</span><span style="color: #000000;">&nbsp;{&nbsp;</span><span style="color: #0000FF;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">true</span><span style="color: #000000;">;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span></div>
<div></div>
<br />3.&nbsp;这里涉及到一个文件名加解密的问题，是为了防止文件具体名称暴露在状态栏中，所以添加一个FileHelper类，代码如下： </div>
</p>
<p>
<div>
<div class="cnblogs_code"><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">class</span><span style="color: #000000;">&nbsp;FileHelper<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;Encrypt(</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;filename)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[]&nbsp;buffer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;HttpContext.Current.Request.ContentEncoding.GetBytes(filename);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">return</span><span style="color: #000000;">&nbsp;HttpUtility.UrlEncode(Convert.ToBase64String(buffer));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;Decrypt(</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;encryptfilename)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[]&nbsp;buffer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Convert.FromBase64String(encryptfilename);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">return</span><span style="color: #000000;">&nbsp;HttpContext.Current.Request.ContentEncoding.GetString(buffer);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span></div>
<div></div>
<br />利用Base64码对文件名进行加解密处理。 <br /><br />4.&nbsp;在Web.config上，添加httpHandlers结点，如下： </div>
</p>
<p>
<divre class="xml"></divre>
<divre></divre><b class="t">
<div class="cnblogs_code"><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">system.web</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">httpHandlers</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">add&nbsp;</span><span style="color: #FF0000;">verb</span><span style="color: #0000FF;">="*"</span><span style="color: #FF0000;">&nbsp;path</span><span style="color: #0000FF;">="download.aspx"</span><span style="color: #FF0000;">&nbsp;type</span><span style="color: #0000FF;">="DownloadHandler"</span><span style="color: #FF0000;">&nbsp;</span><span style="color: #0000FF;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">httpHandlers</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">system.web</span><span style="color: #0000FF;">&gt;</span></div>
<div></div>
</b>
<divre></divre>
<pre></pre>
</p>
<p><br />5.&nbsp;现在新建一个aspx页面，对文件进行下载： <br /><br />Default.aspx代码如下： </p>
<p>
<div>
<div class="cnblogs_code"><img align="top" width="11" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" height="16" onclick="this.style.display='none'; document.getElementById('Code_Closed_Text_103505').style.display='none'; document.getElementById('Code_Open_Image_103505').style.display='inline'; document.getElementById('Code_Open_Text_103505').style.display='inline';" style="display: none" id="Code_Closed_Image_103505" /><img align="top" width="11" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" height="16" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_103505').style.display='none'; getElementById('Code_Closed_Image_103505').style.display='inline'; getElementById('Code_Closed_Text_103505').style.display='inline';" id="Code_Open_Image_103505" /><span id="Code_Closed_Text_103505" class="cnblogs_code_Collapse">Code</span><span id="Code_Open_Text_103505"><br /><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="background-color: #FFFF00; color: #000000;">&lt;%</span><span style="background-color: #F5F5F5; color: #000000;">@&nbsp;Page&nbsp;Language</span><span style="background-color: #F5F5F5; color: #000000;">=</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #800000;">C#</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #000000;">&nbsp;AutoEventWireup</span><span style="background-color: #F5F5F5; color: #000000;">=</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #800000;">true</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #000000;">&nbsp;&nbsp;CodeFile</span><span style="background-color: #F5F5F5; color: #000000;">=</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #800000;">Default.aspx.cs</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #000000;">&nbsp;Inherits</span><span style="background-color: #F5F5F5; color: #000000;">=</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #800000;">_Default</span><span style="background-color: #F5F5F5; color: #800000;">"</span><span style="background-color: #F5F5F5; color: #000000;">&nbsp;</span><span style="background-color: #FFFF00; color: #000000;">%&gt;</span><span style="color: #000000;">&nbsp;<br /><br /></span><span style="color: #0000FF;">&lt;!</span><span style="color: #FF00FF;">DOCTYPE&nbsp;html&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;XHTML&nbsp;1.0&nbsp;Transitional//EN"&nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;">&nbsp;<br /><br /></span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">html&nbsp;</span><span style="color: #FF0000;">xmlns</span><span style="color: #0000FF;">="http://www.w3.org/1999/xhtml"</span><span style="color: #FF0000;">&nbsp;</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">head&nbsp;</span><span style="color: #FF0000;">runat</span><span style="color: #0000FF;">="server"</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">title</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;">文件下载</span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">title</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">head</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">body</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">form&nbsp;</span><span style="color: #FF0000;">id</span><span style="color: #0000FF;">="form1"</span><span style="color: #FF0000;">&nbsp;runat</span><span style="color: #0000FF;">="server"</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">div</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;</span><span style="color: #800000;">asp:HyperLink&nbsp;</span><span style="color: #FF0000;">ID</span><span style="color: #0000FF;">="link"</span><span style="color: #FF0000;">&nbsp;runat</span><span style="color: #0000FF;">="server"</span><span style="color: #FF0000;">&nbsp;Text</span><span style="color: #0000FF;">="文件下载"</span><span style="color: #0000FF;">&gt;&lt;/</span><span style="color: #800000;">asp:HyperLink</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">form</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">body</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span><span style="color: #0000FF;">&lt;/</span><span style="color: #800000;">html</span><span style="color: #0000FF;">&gt;</span><span style="color: #000000;"><br /></span></span></div>
<br />Default.aspx.cs代码如下： </div>
</p>
<p>
<div>
<div class="cnblogs_code"><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Data;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Configuration;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.Security;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI.WebControls;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI.WebControls.WebParts;<br /></span><span style="color: #0000FF;">using</span><span style="color: #000000;">&nbsp;System.Web.UI.HtmlControls;<br /><br /></span><span style="color: #0000FF;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">partial</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">class</span><span style="color: #000000;">&nbsp;_Default&nbsp;:&nbsp;System.Web.UI.Page<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000FF;">void</span><span style="color: #000000;">&nbsp;Page_Load(</span><span style="color: #0000FF;">object</span><span style="color: #000000;">&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">&nbsp;url&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;FileHelper.Encrypt(</span><span style="color: #800000;">"</span><span style="color: #800000;">DesignPattern.chm</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;link.NavigateUrl&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">~/download.aspx?fn=</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;url;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span></div>
<div></div>
<br />这样就实现了文件下载时,不管是什么格式的文件,都能够弹出打开/保存窗口。</div>
</p>
<p>&nbsp;</p>
<div></div><img src="http://www.cnblogs.com/tuyile006/aggbug/1583029.html?type=1" width="1" height="1" alt=""/><p>评论: 1　<a href="http://www.cnblogs.com/tuyile006/archive/2009/10/14/1583029.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/10/14/1583029.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>理解I/O Completion Port 【转】</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575554.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Mon, 28 Sep 2009 03:28:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575554.html</guid><description><![CDATA[<p>阅读: 270 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-28 11:28 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575554.html" target="_blank">原文链接</a></p><p>什么是IOCP</p>
<p>微软在Winsock2中引入了IOCP这一概念 。IOCP全称I/O Completion Port，中文译为I/O完成端口。IOCP是一个异步I/O的API，它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是，一个套接字[socket]与一个完成端口关联了起来，然后就可继续进行正常的Winsock操作了。然而，当一个事件发生的时候，此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。<br />&nbsp;这里我要对上面的一些概念略作补充，在解释[完成]两字之前，我想先简单的提一下同步和异步这两个概念，逻辑上来讲做完一件事后再去做另一件事就是同步，而同时一起做两件或两件以上事的话就是异步了。你也可以拿单线程和多线程来作比喻。但是我们一定要将同步和堵塞，异步和非堵塞区分开来，所谓的堵塞函数诸如accept(&hellip;)，当调用此函数后，此时线程将挂起，直到操作系统来通知它，&rdquo;HEY兄弟，有人连进来了&rdquo;，那个挂起的线程将继续进行工作，也就符合&rdquo;生产者-消费者&rdquo;模型。堵塞和同步看上去有两分相似，但却是完全不同的概念。大家都知道I/O设备是个相对慢速的设备，不论打印机，调制解调器，甚至硬盘，与CPU相比都是奇慢无比的，坐下来等I/O的完成是一件不甚明智的事情，有时候数据的流动率非常惊人，把数据从你的文件服务器中以Ethernet速度搬走，其速度可能高达每秒一百万字节，如果你尝试从文件服务器中读取100KB，在用户的眼光来看几乎是瞬间完成，但是，要知道，你的线程执行这个命令，已经浪费了10个一百万次CPU周期。所以说，我们一般使用另一个线程来进行I/O。重叠IO[overlapped I/O]是Win32的一项技术，你可以要求操作系统为你传送数据，并且在传送完毕时通知你。这也就是[完成]的含义。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上，操作系统内部正是以线程来完成overlapped I/O。你可以获得线程所有利益，而不需要付出什么痛苦的代价。</p>
<p>完成端口中所谓的[端口]并不是我们在TCP/IP中所提到的端口，可以说是完全没有关系。我到现在也没想通一个I/O设备[I/O Device]和端口[IOCP中的Port]有什么关系。估计这个端口也迷惑了不少人。IOCP只不过是用来进行读写操作，和文件I/O倒是有些类似。既然是一个读写设备，我们所能要求它的只是在处理读与写上的高效。在文章的第三部分你会轻而易举的发现IOCP设计的真正用意。<br />&nbsp;</p>
<p><br />IOCP和网络又有什么关系？<br />int main()<br />{<br />&nbsp;WSAStartup(MAKEWORD(2, 2), &amp;wsaData);<br />&nbsp;ListeningSocket = socket(AF_INET, SOCK_STREAM, 0);&nbsp;<br />&nbsp;bind(ListeningSocket, (SOCKADDR*)&amp;ServerAddr, sizeof(ServerAddr));<br />&nbsp;listen(ListeningSocket, 5);<br />&nbsp;int nlistenAddrLen = sizeof(ClientAddr);<br />&nbsp;while(TRUE)<br />&nbsp;{<br />NewConnection = accept(ListeningSocket, (SOCKADDR*)&amp;ClientAddr, &amp;nlistenAddrLen);<br />HANDLE hThread = CreateThread(NULL, 0, ThreadFunc, (void*) NewConnection, 0, &amp;dwTreadId);<br />&nbsp;&nbsp;CloseHandle(hThread);<br />&nbsp;}<br />&nbsp;return 0;<br />}<br />相信只要写过网络的朋友，应该对这样的结构在熟悉不过了。accept后线程被挂起，等待一个客户发出请求，而后创建新线程来处理请求。当新线程处理客户请求时，起初的线程循环回去等待另一个客户请求。处理客户请求的线程处理完毕后终结。<br />&nbsp;在上述的并发模型中，对每个客户请求都创建了一个线程。其优点在于等待请求的线程只需做很少的工作。大多数时间中，该线程在休眠[因为recv处于堵塞状态]。<br />&nbsp;但是当并发模型应用在服务器端[基于Windows NT]，Windows NT小组注意到这些应用程序的性能没有预料的那么高。特别的，处理很多同时的客户请求意味着很多线程并发地运行在系统中。因为所有这些线程都是可运行的[没有被挂起和等待发生什么事]，Microsoft意识到NT内核花费了太多的时间来转换运行线程的上下文[Context]，线程就没有得到很多CPU时间来做它们的工作。</p>
<p><clk style="font-size: 14px; line-height: 19pt;"></clk><clk></clk>大家都感觉到并行模型的瓶颈在于它为每一个客户请求都创建了一个新<nobr onmouseout="$cE.OuK()" onclick="$cE.c(event,4,&quot;&quot;,1)" style="font-size: 14px; color: #6600ff; line-height: 19pt; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline;" onmouseover="$cE.s(event,4)" id="clickeyekey4" onmousemove="$cE.MoW()" oncontextmenu="return false">线程</nobr>。创建线程比起创建进程开销要小，但也远不是没有开销的。<clk></clk><clk></clk><br /><clk style="font-size: 14px; line-height: 19pt;"></clk><clk></clk>我们不妨设想一下：如果事先开好N个线程，让它们在那hold[堵塞]，然后可以将所有用户的请求都投递到一个消息队列中去。然后那N个线程逐一从消息队列中去取出消息并加以处理。就可以避免针对每一个用户请求都开线程。不仅<nobr onmouseout="$cE.OuK()" onclick="$cE.c(event,1,&quot;&quot;,1)" style="font-size: 14px; color: #6600ff; line-height: 19pt; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline;" onmouseover="$cE.s(event,1)" id="clickeyekey1" onmousemove="$cE.MoW()" oncontextmenu="return false">减少</nobr>了线程的资源，也提高了线程的利用率。理论上很不错，你想我等泛泛之辈都能想出来的问题，Microsoft又怎会没有考虑到呢?!<clk></clk><clk></clk><br />这个问题的解决方法就是一个称为I/O完成端口的内核对象，他首次在Windows NT3.5中被引入。<br />其实我们上面的构想应该就差不多是IOCP的设计机理。其实说穿了IOCP不就是一个消息队列嘛！你说这和[端口]这两字有何联系。我的理解就是IOCP最多是应用程序和操作系统沟通的一个接口罢了。<br />至于IOCP的具体设计那我也很难说得上来，毕竟我没看过实现的代码，但你完全可以进行模拟，只不过性能可能&hellip;，如果想深入理解IOCP， Jeffrey Ritchter的Advanced Windows 3rd其中第13章和第14张有很多宝贵的内容，你可以拿来窥视一下系统是如何完成这一切的。</p>
<p>&nbsp;</p>
<p>实现方法<br />Microsoft为IOCP提供了相应的API函数，主要的就两个，我们逐一的来看一下：<br />HANDLE CreateIoCompletionPort (<br />&nbsp; HANDLE FileHandle,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // handle to file<br />&nbsp; HANDLE ExistingCompletionPort,&nbsp;&nbsp;&nbsp;&nbsp; // handle to I/O completion port<br />&nbsp; ULONG_PTR CompletionKey,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // completion key<br />&nbsp; DWORD NumberOfConcurrentThreads // number of threads to execute concurrently<br />);<br />&nbsp;在讨论各参数之前，首先要注意该函数实际用于两个截然不同的目的：<br />&nbsp;&nbsp;1．用于创建一个完成端口对象<br />&nbsp;&nbsp;2．将一个句柄[HANDLE]和完成端口关联到一起<br />&nbsp;在创建一个完成一个端口的时候，我们只需要填写一下NumberOfConcurrentThreads这个参数就可以了。它告诉系统一个完成端口上同时允许运行的线程最大数。在默认情况下，所开线程数和CPU数量相同，但经验给我们一个公式：<br />&nbsp;&nbsp;线程数 = CPU数 * 2 + 2<br />&nbsp;要使完成端口有用，你必须把它同一个或多个设备相关联。这也是调用CreateIoCompletionPort完成的。你要向该函数传递一个已有的完成端口的句柄，我们既然要处理网络事件，那也就是将客户的socket作为HANDLE传进去。和一个完成键[对你有意义的一个32位值，也就是一个指针，操作系统并不关心你传什么]。每当你向端口关联一个设备时，系统向该完成端口的设备列表中加入一条信息纪录。</p>
<p>另一个API就是<br />BOOL GetQueuedCompletionStatus(<br />&nbsp; HANDLE CompletionPort,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // handle to completion port<br />&nbsp; LPDWORD lpNumberOfBytes,&nbsp;&nbsp;&nbsp;&nbsp; // bytes transferred<br />&nbsp; PULONG_PTR lpCompletionKey,&nbsp; // file completion key<br />&nbsp; LPOVERLAPPED *lpOverlapped,&nbsp; // buffer<br />&nbsp; DWORD dwMilliseconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // optional timeout value<br />);<br /><clk style="font-size: 14px; line-height: 19pt;"></clk><clk></clk>&nbsp;第一个参数指出了线程要监视哪一个完成端口。很多<nobr onmouseout="$cE.OuK()" onclick="$cE.c(event,0,&quot;&quot;,1)" style="font-size: 14px; color: #6600ff; line-height: 19pt; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline;" onmouseover="$cE.s(event,0)" id="clickeyekey0" onmousemove="$cE.MoW()" oncontextmenu="return false">服务</nobr>应用程序只是使用一个I/O完成端口，所有的I/O请求完成以后的通知都将发给该端口。简单的说，GetQueuedCompletionStatus使调用线程挂起，直到指定的端口的I/O完成队列中出现了一项或直到超时。同I/O完成端口相关联的第3个数据结构是使线程得到完成I/O项中的信息：传输的字节数，完成键和OVERLAPPED结构的地址。该信息是通过传递给GetQueuedCompletionSatatus的lpdwNumberOfBytesTransferred，lpdwCompletionKey和lpOverlapped参数返回给线程的。<clk></clk><clk></clk></p>
<p>&nbsp;根据到目前为止已经讲到的东西，首先来构建一个frame。下面为您说明了如何使用完成端口来开发一个echo服务器。大致如下：<br />&nbsp;1.初始化Winsock<br />&nbsp;2.创建一个完成端口<br />&nbsp;3.根据服务器线程数创建一定量的线程数<br />&nbsp;4.准备好一个socket进行bind然后listen<br />&nbsp;5.进入循环accept等待客户请求<br />&nbsp;6.创建一个数据结构容纳socket和其他相关信息<br />&nbsp;7.将连进来的socket同完成端口相关联<br />&nbsp;8.投递一个准备接受的请求<br />&nbsp;以后就不断的重复5至8的过程</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>关于.Net中如何实现IOCP的文章：<br />http://msdn.microsoft.com/zh-cn/magazine/cc163356.aspx<br />http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx</p><img src="http://www.cnblogs.com/tuyile006/aggbug/1575554.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575554.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575554.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Socket笔记【转】</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575543.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Mon, 28 Sep 2009 03:23:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575543.html</guid><description><![CDATA[<p>阅读: 526 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-28 11:23 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575543.html" target="_blank">原文链接</a></p><p><b style="mso-bidi-font-weight: normal;"><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial; mso-fareast-font-family: Arial;" lang="EN-US"><span style="mso-list: Ignore;">1、<span style="font: 7pt &quot;Times New Roman&quot;;">&nbsp; </span></span></span></b><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">为了增加效率，可以考虑采用无异常的函数</span></strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">在</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">.net2.0</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">中</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Send,Socket.Receive </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">有了无异常的函数</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br />Socket.Send(Byte[], Int32, Int32, SocketFlags, SocketError) <br />Socket.Receive(Byte[], Int32, Int32, SocketFlags, SocketError) <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">减少不必要的异常，就等于增加效率。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> </span></p>
<p><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"><strong><span style="font-family: Arial;">2</span></strong></span><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">、</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Connected </span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">不是当前的</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">状态</span></strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br />MSDN</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">原文：获取一个值，该值指示</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Socket </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">是在上次</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Send </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">还是</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Receive </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">操作时连接到远程主机。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">应当如何解决呢？</span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"><o:p></o:p></span></span></p>
<p><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">同样</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">MSDN</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">也告诉了我们：</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br />Connected </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">属性的值反映最近操作时的连接状态。如果您需要确定连接的当前状态，请进行非阻止、零字节的</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Send </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">调用。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;"> </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">如果该调用成功返回或引发</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> WAEWOULDBLOCK </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">错误代码</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> (10035)</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，则该套接字仍然处于连接状态；否则，该套接字不再处于连接状态。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /><strong><span style="font-family: Arial;">3</span></strong></span><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">、要用</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Poll</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">判断是否可以接收，不要用</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Available</span></strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">虽然</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Available</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">可以偷窥到当前</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Recv</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">缓冲区字节数，而且</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Available</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">是</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Poll</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">速度的两倍，但是</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">MSDN</span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">说到</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">：如果远程主机使用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Shutdown </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">方法关闭了</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Socket </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">连接，并且所有可用数据均已收到，则</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Receive </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">方法将立即完成并返回零字节。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">所以当网络断开的时候单纯使用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Available</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">判断是否</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">recv</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">到数据会存在不知道客户端已经断开</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Bug <br /></span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">补充：</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">不推荐使用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Poll</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">对</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">的列表遍历，应当使用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Select</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">（或者其他模型），</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Poll</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">是对</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Select</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">的封装，执行</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Poll</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">耗时是非阻塞</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket.Recv</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">的三倍。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /><strong><span style="font-family: Arial;">4</span></strong></span><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">、非阻塞模式不能采用</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Receive</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">的返回值表示是否断开</span></strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">第</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">3</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">条说道：如果远程主机使用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Shutdown </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">方法关闭了</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Socket </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">连接，并且所有可用数据均已收到，则</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Receive </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">方法将立即完成并返回零字节。但这并不能阻塞模式说明</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket</span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">已经断开，</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">这一条和</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">C</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">的</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">recv</span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">函数不同，需要特别注意</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">。需要判断</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">out</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">出来的</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，当不为</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError.Success</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">、</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError.Interrupted</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">和</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError.WouldBlock</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">时就可以认为网络已经断开。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /><strong><span style="font-family: Arial;">5</span></strong></span><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">、</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Send</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">可能出现缓冲区满的情况</span></strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">判断</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">out</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">出来的</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，如果等于</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError.WouldBlock</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，则是</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Send</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">缓冲区已满，应断开该</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，否则影响整体速度，而不应当</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">again, </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">反过来说允许的错误码只有</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">SocketError.Interrupted</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，此时可以重来一次。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /><strong><span style="font-family: Arial;">6</span></strong></span><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">、主动断开</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket </span></strong><b><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"><br /></span></b><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">MSDN</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">说道</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">:</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">如果当前使用的是面向连接的</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Socket</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，则必须先调用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Shutdown </span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">方法，然后才能关闭</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Socket</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">。这可以确保在已连接的套接字关闭之前，已发送和接收该套接字上的所有数据。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">所以，网络库的</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Close</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">函数可以封装为先调用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> Shutdown(SocketShutdown.Both)</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">，在调用</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Close()</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">。</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /><strong><span style="font-family: Arial;">7</span></strong></span><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">、</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Socket</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">已经关闭</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">(Close)</span></strong><strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: 宋体; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">但不能在另一端断开</span></strong><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"> <br /></span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">一端</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">Scoket</span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">已经关闭了，但另一端短时间内仍可以发送数据！这个问题还没有找到解决办法的，但原因已知，</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">在《</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">Windows</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">网络编程技术》一书</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">(P139-P140)</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">中说道</span></span><span style="font-size: 9pt; color: red; line-height: 170%; font-family: Arial;" lang="EN-US">:</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">被动关闭的情况下，应用程序会从对方那里接收一个</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">FIN</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">包，并用一个</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">ACK</span><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;"><span style="font-family: 宋体;">包做出响应。此时，应用程序的套接字会变成</span></span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US">ClOSE_WAIT</span><span style="font-family: 宋体;"><span style="font-size: 9pt; color: #333333; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">状态。由于对方已关闭自己的套接字，所以不能再发送数据了。</span><span style="font-size: 9pt; color: red; line-height: 170%; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial;">但应用程序却不同，它能一直发送数据，直到对方的套接字已关闭为止。</span><span style="font-size: 9pt; color: #333333; line-height: 170%; font-family: Arial;" lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p><span style="font-family: Times New Roman;">&nbsp;</span></o:p></span></p><img src="http://www.cnblogs.com/tuyile006/aggbug/1575543.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575543.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/28/1575543.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>数学之美 系列十七 闪光的不一定是金子 谈谈搜索引擎作弊问题(Search Engine Anti-SPAM)</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564813.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Fri, 11 Sep 2009 07:09:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564813.html</guid><description><![CDATA[<p>阅读: 243 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-11 15:09 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564813.html" target="_blank">原文链接</a></p><div id="read_4291" class="f14">
<h4>数学之美 系列十七 闪光的不一定是金子 谈谈搜索引擎作弊问题(Search Engine Anti-SPAM)</h4>
<div class="tpc_content">自从有了搜索引擎，就有了针对搜索引擎网页排名的作弊(SPAM)。以至于用户发现在搜索引擎中排名靠前的网页不一定就是高质量的，用句俗话说，闪光的不一定是金子。<br /><br />搜索引擎的作弊，虽然方法很多，目的只有一个，就是采用不正当手段提高自己网页的排名。早期最常见的作弊方法是重复关键词。比如一个卖数码相机的网站，重复地罗列各种数码相机的品牌，如尼康、佳能和柯达等等。为了不让读者看到众多讨厌的关键词，聪明一点的作弊者常用很小的字体和与背景相同的颜色来掩盖这些关键词。其实，这种做法很容易被搜索引擎发现并纠正。<br /><br />在有了网页排名(page rank)以后，作弊者发现一个网页被引用的连接越多，排名就可能越靠前，于是就有了专门卖链接和买链接的生意。比如，有人自己创建成百上千个网站，这些网站上没有实质的内容，只有到他们的客户网站的连接。这种做法比重复关键词要高明得多，但是还是不太难被发现。因为那些所谓帮别人提高排名的网站，为了维持生意需要大量地卖链接，所以很容易露马脚。（这就如同造假钞票，当某一种假钞票的流通量相当大以后，就容易找到根源了。）再以后，又有了形形色色的作弊方式，我们就不在这里一一赘述了。<br /><br />几年前，我加入Google做的第一件事就是消除网络作弊。在Google最早发现搜索引擎作弊的是Matt Cutts，他在我加入Google前几个月开始研究这个问题，后来，辛格，马丁和我先后加入进来。我们经过几个月的努力，清除了一半的作弊者。(当然，以后抓作弊的效率就不会有这么高了。）其中一部分网站从此"痛改前非"，但是还是有很多网站换一种作弊方法继续作弊，因此，抓作弊成了一种长期的猫捉老鼠的游戏。虽然至今还没有一个一劳永逸地解决作弊问题的方法，但是，Google基本做到了对于任何已知的作弊方法，在一定时间内发现并清除它，从而总是将作弊的网站的数量控制在一个很小的比例范围。<br /><br />抓作弊的方法很像信号处理中的去噪音的办法。学过信息论和有信号处理经验的读者可能知道这么一个事实，我们如果在发动机很吵的汽车里用手机打电话，对方可能听不清；但是如果我们知道了汽车发动机的频率，我们可以加上一个和发动机噪音相反的信号，很容易地消除发动机的噪音，这样，收话人可以完全听不到汽车的噪音。事实上，现在一些高端的手机已经有了这种检测和消除噪音的功能。消除噪音的流程可以概括如下：<br /><img border="0" width="892" src="http://googlechinablog.com/uploaded_images/math-782969.gif" height="568" /><br />在图中，原始的信号混入了噪音，在数学上相当于两个信号做卷积。噪音消除的过程是一个解卷积的过程。这在信号处理中并不是什么难题。因为第一，汽车发动机的频率是固定的，第二，这个频率的噪音重复出现，只要采集几秒钟的信号进行处理就能做到。从广义上讲，只要噪音不是完全随机的、并且前后有相关性，就可以检测到并且消除。（事实上，完全随机不相关的高斯白噪音是很难消除的。）<br /><br />搜索引擎的作弊者所作的事，就如同在手机信号中加入了噪音，使得搜索结果的排名完全乱了。但是，这种人为加入的噪音并不难消除，因为作弊者的方法不可能是随机的（否则就无法提高排名了）。而且，作弊者也不可能是一天换一种方法，即作弊方法是时间相关的。因此，搞搜索引擎排名算法的人，可以在搜集一段时间的作弊信息后，将作弊者抓出来，还原原有的排名。当然这个过程需要时间，就如同采集汽车发动机噪音需要时间一样，在这段时间内，作弊者可能会尝到些甜头。因此，有些人看到自己的网站经过所谓的优化（其实是作弊），排名在短期内靠前了，以为这种所谓的优化是有效的。但是，不久就会发现排名掉下去了很多。这倒不是搜索引擎以前宽容，现在严厉了，而是说明抓作弊需要一定的时间，以前只是还没有检测到这些作弊的网站而已。<br /><br />还要强调一点，Google抓作弊和恢复网站原有排名的过程完全是自动的(并没有个人的好恶），就如同手机消除噪音是自动的一样。一个网站要想长期排名靠前，就需要把内容做好，同时要和那些作弊网站划清界限。</div>
</div><img src="http://www.cnblogs.com/tuyile006/aggbug/1564813.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564813.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564813.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>数学之美 系列十六 （下）－ 不要把所有的鸡蛋放在一个篮子里　最大熵模型</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564809.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Fri, 11 Sep 2009 07:08:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564809.html</guid><description><![CDATA[<p>阅读: 176 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-11 15:08 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564809.html" target="_blank">原文链接</a></p><div id="read_4290" class="f14">
<h4>数学之美 系列十六 （下）－ 不要把所有的鸡蛋放在一个篮子里　最大熵模型</h4>
<div class="tpc_content">我们上次谈到用最大熵模型可以将各种信息综合在一起。我们留下一个问题没有回答，就是如何构造最大熵模型。我们已经所有的最大熵模型都是指数函数的形式，现在只需要确定指数函数的参数就可以了，这个过程称为模型的训练。<br /><br />最原始的最大熵模型的训练方法是一种称为通用迭代算法 GIS(generalized iterative scaling) 的迭代 算法。GIS 的原理并不复杂，大致可以概括为以下几个步骤：<br />1. 假定第零次迭代的初始模型为等概率的均匀分布。<br />2. 用第 N 次迭代的模型来估算每种信息特征在训练数据中的分布，如果超过了实际的，就把相应的模型参数变小；否则，将它们便大。<br />3. 重复步骤 2 直到收敛。<br /><br />GIS 最早是由 Darroch 和 Ratcliff 在七十年代提出的。但是，这两人没有能对这种算法的物理含义进行很好地解释。后来是由数学家希萨（Csiszar)解释清楚的，因此，人们在谈到这个算法时，总是同时引用 Darroch 和Ratcliff 以及希萨的两篇论文。GIS 算法每次迭代的时间都很长，需要迭代很多次才能收敛，而且不太稳定，即使在 64 位计算机上都会出现溢出。因此，在实际应用中很少有人真正使用 GIS。大家只是通过它来了解最大熵模型的算法。<br /><br />八十年代，很有天才的孪生兄弟的达拉皮垂(Della Pietra)在 IBM 对 GIS 算法进行了两方面的改进，提出了改进迭代算法 IIS（improved iterative scaling）。这使得最大熵模型的训练时间缩短了一到两个数量级。这样最大熵模型才有可能变得实用。即使如此，在当时也只有 IBM 有条件是用最大熵模型。<br /><br />由于最大熵模型在数学上十分完美，对科学家们有很大的诱惑力，因此不少研究者试图把自己的问题用一个类似最大熵的近似模型去套。谁知这一近似，最大熵模型就变得不完美了，结果可想而知，比打补丁的凑合的方法也好不了多少。于是，不少热心人又放弃了这种方法。第一个在实际信息处理应用中验证了最大熵模型的优势的，是宾夕法尼亚大学马库斯的另一个高徒原 IBM 现微软的研究员拉纳帕提(Adwait Ratnaparkhi)。拉纳帕提的聪明之处在于他没有对最大熵模型进行近似，而是找到了几个最适合用最大熵模型、而计算量相对不太大的自然语言处理问题，比如词性标注和句法分析。拉纳帕提成功地将上下文信息、词性（名词、动词和形容词等）、句子成分（主谓宾）通过最大熵模型结合起来，做出了当时世界上最好的词性标识系统和句法分析器。拉纳帕提的论文发表后让人们耳目一新。拉纳帕提的词性标注系统，至今仍然是使用单一方法最好的系统。科学家们从拉纳帕提的成就中，又看到了用最大熵模型解决复杂的文字信息处理的希望。<br /><br />但是，最大熵模型的计算量仍然是个拦路虎。我在学校时花了很长时间考虑如何简化最大熵模型的计算量。终于有一天，我对我的导师说，我发现一种数学变换，可以将大部分最大熵模型的训练时间在 IIS 的基础上减少两个数量级。我在黑板上推导了一个多小时，他没有找出我的推导中的任何破绽，接着他又回去想了两天，然后告诉我我的算法是对的。从此，我们就建造了一些很大的最大熵模型。这些模型比修修补补的凑合的方法好不少。即使在我找到了快速训练算法以后，为了训练一个包含上下文信息，主题信息和语法信息的文法模型(language model)，我并行使用了 20 台当时最快的 SUN 工作站，仍然计算了三个月。由此可见最大熵模型的复杂的一面。最大熵模型快速算法的实现很复杂，到今天为止，世界上能有效实现这些算法的人也不到一百人。有兴趣实现一个最大熵模型的读者可以阅读我的论文。<br /><br />最大熵模型，可以说是集简与繁于一体，形式简单，实现复杂。值得一提的是，在Google的很多产品中，比如机器翻译，都直接或间接地用到了最大熵模型。<br /><br />讲到这里，读者也许会问，当年最早改进最大熵模型算法的达拉皮垂兄弟这些年难道没有做任何事吗？他们在九十年代初贾里尼克离开 IBM 后，也退出了学术界，而到在金融界大显身手。他们两人和很多 IBM 语音识别的同事一同到了一家当时还不大，但现在是世界上最成功对冲基金(hedge fund)公司----文艺复兴技术公司 (Renaissance Technologies)。我们知道，决定股票涨落的因素可能有几十甚至上百种，而最大熵方法恰恰能找到一个同时满足成千上万种不同条件的模型。达拉皮垂兄弟等科学家在那里，用于最大熵模型和其他一些先进的数学工具对股票预测，获得了巨大的成功。从该基金 1988 年创立至今，它的净回报率高达平均每年 34%。也就是说，如果 1988 年你在该基金投入一块钱，今天你能得到 200 块钱。这个业绩，远远超过股神巴菲特的旗舰公司伯克夏哈撒韦（Berkshire Hathaway)。同期，伯克夏哈撒韦的总回报是 16 倍。<br /><br />值得一提的是，信息处理的很多数学手段，包括隐含马尔可夫模型、子波变换、贝叶斯网络等等，在华尔街多有直接的应用。由此可见，数学模型的作用。</div>
</div><img src="http://www.cnblogs.com/tuyile006/aggbug/1564809.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564809.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564809.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>数学之美 系列十六（上） 不要把所有的鸡蛋放在一个篮子里 -- 谈谈最大熵模型</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564806.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Fri, 11 Sep 2009 07:08:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564806.html</guid><description><![CDATA[<p>阅读: 152 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-11 15:08 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564806.html" target="_blank">原文链接</a></p><div id="read_4288" class="f14">
<h4>数学之美 系列十六（上） 不要把所有的鸡蛋放在一个篮子里 -- 谈谈最大熵模型</h4>
<div class="tpc_content">[我们在投资时常常讲不要把所有的鸡蛋放在一个篮子里，这样可以降低风险。在信息处理中，这个原理同样适用。在数学上，这个原理称为<a target="_blank" href="http://www.wljx.sdu.edu.cn/wlwz/reading/r_infor/shang7.htm"><span style="color: #2f5fa1;">最大熵原理</span></a>(the maximum entropy principle)。这是一个非常有意思的题目，但是把它讲清楚要用两个系列的篇幅。]<br /><br />前段时间，Google 中国研究院的刘骏总监谈到在网络搜索排名中，用到的信息有上百种。更普遍地讲，在自然语言处理中，我们常常知道各种各样的但是又不完全确定的信息，我们需要用一个统一的模型将这些信息综合起来。如何综合得好，是一门很大的学问。<br /><br />让我们看一个拼音转汉字的简单的例子。假如输入的拼音是"wang-xiao-bo"，利用语言模型，根据有限的上下文(比如前两个词)，我们能给出两个最常见的名字&ldquo;王小波&rdquo;和&ldquo;王晓波&rdquo;。至于要唯一确定是哪个名字就难了，即使利用较长的上下文也做不到。当然，我们知道如果通篇文章是介绍文学的，作家王小波的可能性就较大；而在讨论两岸关系时，台湾学者王晓波的可能性会较大。在上面的例子中，我们只需要综合两类不同的信息，即主题信息和上下文信息。虽然有不少凑合的办法，比如：分成成千上万种的不同的主题单独处理，或者对每种信息的作用加权平均等等，但都不能准确而圆满地解决问题，这样好比以前我们谈到的行星运动模型中的<a target="_blank" href="http://googlechinablog.com/2006/08/blog-post_09.html"><span style="color: #2f5fa1;">小圆套大圆</span></a>打补丁的方法。在很多应用中，我们需要综合几十甚至上百种不同的信息，这种小圆套大圆的方法显然行不通。<br /><br />数学上最漂亮的办法是最大熵(maximum entropy)模型，它相当于行星运动的椭圆模型。&ldquo;最大熵&rdquo;这个名词听起来很深奥，但是它的原理很简单，我们每天都在用。说白了，就是要保留全部的不确定性，将风险降到最小。让我们来看一个实际例子。<br /><br />有一次，我去 AT&amp;T 实验室作关于最大熵模型的报告，我带去了一个色子。我问听众&ldquo;每个面朝上的概率分别是多少&rdquo;，所有人都说是等概率，即各点的概率均为1/6。这种猜测当然是对的。我问听众们为什么，得到的回答是一致的：对这个&ldquo;一无所知&rdquo;的色子，假定它每一个朝上概率均等是最安全的做法。（你不应该主观假设它象韦小宝的色子一样灌了铅。）从投资的角度看，就是风险最小的做法。从信息论的角度讲，就是保留了最大的不确定性，也就是说让熵达到最大。接着，我又告诉听众，我的这个色子被我特殊处理过，已知四点朝上的概率是三分之一，在这种情况下，每个面朝上的概率是多少？这次，大部分人认为除去四点的概率是 1/3，其余的均是 2/15，也就是说已知的条件（四点概率为 1/3）必须满足，而对其余各点的概率因为仍然无从知道，因此只好认为它们均等。注意，在猜测这两种不同情况下的概率分布时，大家都没有添加任何主观的假设，诸如四点的反面一定是三点等等。（事实上，有的色子四点反面不是三点而是一点。）这种基于直觉的猜测之所以准确，是因为它恰好符合了最大熵原理。<br /><br />最大熵原理指出，当我们需要对一个随机事件的概率分布进行预测时，我们的预测应当满足全部已知的条件，而对未知的情况不要做任何主观假设。（不做主观假设这点很重要。）在这种情况下，概率分布最均匀，预测的风险最小。因为这时概率分布的信息熵最大，所以人们称这种模型叫&ldquo;最大熵模型&rdquo;。我们常说，不要把所有的鸡蛋放在一个篮子里，其实就是最大熵原理的一个朴素的说法，因为当我们遇到不确定性时，就要保留各种可能性。<br /><br />回到我们刚才谈到的拼音转汉字的例子，我们已知两种信息，第一，根据语言模型，wang-xiao-bo 可以被转换成王晓波和王小波；第二，根据主题，王小波是作家，《黄金时代》的作者等等，而王晓波是台湾研究两岸关系的学者。因此，我们就可以建立一个最大熵模型，同时满足这两种信息。现在的问题是，这样一个模型是否存在。匈牙利著名数学家、信息论最高奖香农奖得主希萨（Csiszar）证明，对任何一组不自相矛盾的信息，这个最大熵模型不仅存在，而且是唯一的。而且它们都有同一个非常简单的形式 -- 指数函数。下面公式是根据上下文（前两个词）和主题预测下一个词的最大熵模型，其中 w3 是要预测的词（王晓波或者王小波）w1 和 w2 是它的前两个字（比如说它们分别是&ldquo;出版&rdquo;，和&ldquo;&rdquo;），也就是其上下文的一个大致估计，subject 表示主题。<br /><br /><img border="0" src="http://googlechinablog.com/uploaded_images/formula-738534.jpg" /><br /><br />我们看到，在上面的公式中，有几个参数 lambda 和 Z ，他们需要通过观测数据训练出来。<br /><br />最大熵模型在形式上是最漂亮的统计模型，而在实现上是最复杂的模型之一。我们在将下一个系列中介绍如何训练最大熵模型的诸多参数，以及最大熵模型在自然语言处理和金融方面很多有趣的应用。</div>
</div><img src="http://www.cnblogs.com/tuyile006/aggbug/1564806.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564806.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564806.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>数学之美 系列十五 繁与简 自然语言处理的几位精英</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564803.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Fri, 11 Sep 2009 07:07:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564803.html</guid><description><![CDATA[<p>阅读: 184 评论: 1 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-11 15:07 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564803.html" target="_blank">原文链接</a></p><div id="read_4287" class="f14">
<h3><a name="115634657041368311"><span style="color: #0070af;">数学之美 系列十五 繁与简 自然语言处理的几位精英</span></a></h3>
<p class="byline-timestamp"><span id="time115634657041368311"></span></p>

<div style="clear: both;"></div>
<span style="color: #666666;"><span class="byline-author">发表者：吴军，Google 研究员 </span><br /><br /></span>我在数学之美系列中一直强调的一个好方法就是简单。但是，事实上，自然语言处理中也有一些特例，比如有些学者将一个问题研究到极致，执著追求完善甚至可以说完美的程度。他们的工作对同行有很大的参考价值，因此我们在科研中很需要这样的学者。在自然语言处理方面新一代的顶级人物麦克尔 &middot; 柯林斯 (<a target="_blank" href="http://www.google.cn/search?hl=zh-CN&amp;newwindow=1&amp;q=Michael+Collins&amp;btnG=%E6%90%9C%E7%B4%A2&amp;meta="><span style="color: #0070af;">Michael Collins</span></a>) 就是这样的人。<br /><br /><span style="font-weight: bold;"><br />柯林斯：追求完美 </span><br /><br />柯林斯从师于自然语言处理大师马库斯 (Mitch Marcus)（我们以后还会多次提到马库斯），从宾夕法利亚大学获得博士学位，现任麻省理工学院 (MIT) 副教授（别看他是副教授，他的水平在当今自然语言处理领域是数一数二的），在作博士期间，柯林斯写了一个后来以他名字命名的自然语言文法分析器 (sentence parser)，可以将书面语的每一句话准确地进行文法分析。文法分析是很多自然语言应用的基础。虽然柯林斯的师兄布莱尔 (Eric Brill) 和 Ratnaparkhi 以及师弟 Eisnar 都完成了相当不错的语言文法分析器，但是柯林斯却将它做到了极致，使它在相当长一段时间内成为世界上最好的文法分析器。柯林斯成功的关键在于将文法分析的每一个细节都研究得很仔细。柯林斯用的数学模型也很漂亮，整个工作可以用完美来形容。我曾因为研究的需要，找柯林斯要过他文法分析器的源程序，他很爽快地给了我。我试图将他的程序修改一下来满足我特定应用的要求，但后来发现，他的程序细节太多以至于很难进一步优化。<a target="_blank" href="http://scholar.google.com/scholar?q=Michael+Collins&amp;ie=UTF-8&amp;amp;amp;amp;amp;amp;oe=UTF-8&amp;hl=en&amp;btnG=Search"><span style="color: #0070af;">柯林斯的博士论文</span></a>堪称是自然语言处理领域的范文。它像一本优秀的小说，把所有事情的来龙去脉介绍的清清楚楚，对于任何有一点计算机和自然语言处理知识的人，都可以轻而易举地读懂他复杂的方法。<br /><br />柯林斯毕业后，在 AT&amp;T 实验室度过了三年快乐的时光。在那里柯林斯完成了许多世界一流的研究工作诸如隐含马尔科夫模型的区别性训练方法，卷积核在自然语言处理中的应用等等。三年后，AT&amp;T 停止了自然语言处理方面的研究，柯林斯幸运地在 MIT 找到了教职。在 MIT 的短短几年间，柯林斯多次在国际会议上获得最佳论文奖。相比其他同行，这种成就是独一无二的。柯林斯的特点就是把事情做到极致。如果说有人喜欢&ldquo;繁琐哲学&rdquo;，柯林斯就是一个。<br /><br /><span style="font-weight: bold;"><br />布莱尔：简单才美 </span><br /><br />在研究方法上，站在柯林斯对立面的典型是他的师兄艾里克 &middot; 布莱尔 (<a target="_blank" href="http://www.cs.jhu.edu/~brill/"><span style="color: #0070af;">Eric Brill</span></a>) 和雅让斯基，后者我们已经介绍过了，这里就不再重复。与柯林斯从工业界到学术界相反，布莱尔职业路径是从学术界走到工业界。与柯里斯的研究方法相反，布莱尔总是试图寻找简单得不能再简单的方法。布莱尔的成名作是基于变换规则的机器学习方法 (transformation rule based machine learning)。这个方法名称虽然很复杂，其实非常简单。我们以拼音转换字为例来说明它：<br /><br />第一步，我们把每个拼音对应的汉字中最常见的找出来作为第一遍变换的结果，当然结果有不少错误。比如，&ldquo;常识&rdquo;可能被转换成&ldquo;长识&rdquo;；<br /><br />第二步，可以说是&ldquo;去伪存真&rdquo;，我们用计算机根据上下文，列举所有的同音字替换的规则，比如，如果 chang 被标识成&ldquo;长&rdquo;，但是后面的汉字是&ldquo;识&rdquo;，则将&ldquo;长&rdquo;改成&ldquo;常&rdquo;；<br /><br />第三步，应该就是&ldquo;去粗取精&rdquo;，将所有的规则用到事先标识好的语料中，挑出有用的，删掉无用的。然后重复二三步，直到找不到有用的为止。<br /><br />布莱尔就靠这么简单的方法，在很多自然语言研究领域，得到了几乎最好的结果。由于他的方法再简单不过了，许许多多的人都跟着学。布莱尔可以算是我在美国的第一个业师，我们俩就用这么简单的方法作词性标注 (part of speech tagging)，也就是把句子中的词标成名词动词，很多年内无人能超越。（最后超越我们的是后来加入 Google 的一名荷兰工程师，用的是同样的方法，但是做得细致很多）布莱尔离开学术界后去了微软研究院。在那里的第一年，他一人一年完成的工作比组里其他所有人许多年做的工作的总和还多。后来，布莱尔又加入了一个新的组，依然是高产科学家。据说，他的工作真正被微软重视要感谢 Google，因为有了 Google，微软才对他从人力物力上给于了巨大的支持，使得布莱尔成为微软搜索研究的领军人物之一。在研究方面，布莱尔有时不一定能马上找到应该怎么做，但是能马上否定掉一种不可能的方案。这和他追求简单的研究方法有关，他能在短时间内大致摸清每种方法的好坏。<br /><br />由于布莱尔总是找简单有效的方法，而又从不隐瞒自己的方法，所以他总是很容易被包括作者我自己在内的很多人赶上和超过。好在布莱尔很喜欢别人追赶他，因为，当人们在一个研究方向超过他时，他已经调转船头驶向它方了。一次，艾里克对我说，有一件事我永远追不上他，那就是他比我先有了第二个孩子 ：）<br /><br />在接下来了系列里，我们还会介绍一个繁与简结合的例子。</div><img src="http://www.cnblogs.com/tuyile006/aggbug/1564803.html?type=1" width="1" height="1" alt=""/><p>评论: 1　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564803.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564803.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>数学之美 十四 谈谈数学模型的重要性</title><link>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564802.html</link><dc:creator>小y</dc:creator><author>小y</author><pubDate>Fri, 11 Sep 2009 07:06:00 GMT</pubDate><guid>http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564802.html</guid><description><![CDATA[<p>阅读: 154 评论: 0 作者: <a href="http://www.cnblogs.com/tuyile006/" target="_blank">小y</a> 发表于 2009-09-11 15:06 <a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564802.html" target="_blank">原文链接</a></p><div id="read_4286" class="f14">
<h3><a name="115495678350668502"><span style="color: #0070af;">数学之美 十四 谈谈数学模型的重要性</span></a></h3>

<div style="clear: both;"></div>
<span style="color: #666666;"><span class="byline-author">发表者：吴军，Google 研究员 </span><br /><br /></span>[注：一直关注数学之美系列的读者可能已经发现，我们对任何问题总是在找相应的准确的数学模型。为了说明模型的重要性，今年七月份我在 Google 中国内部讲课时用了整整一堂课来讲这个问题，下面的内容是我讲座的摘要。］<br /><br />在包括哥白尼、伽利略和牛顿在内的所有天文学家中，我最佩服的是地心说的提出者托勒密。虽然天文学起源于古埃及，并且在古巴比伦时，人们就观测到了五大行星（金、木、水、火、土）运行的轨迹，以及行星在近日点运动比远日点快。（下图是在地球上看到的金星的轨迹，看过达芬奇密码的读者知道金星大约每四年在天上画一个五角星。）<br /><br /><img border="0" src="http://googlechinablog.com/uploaded_images/Picture2-758642.jpg" style="border: 1px solid;" /><br /><br />但是真正创立了天文学，并且计算出诸多天体运行轨迹的是两千年前古罗马时代的托勒密。虽然今天我们可能会嘲笑托勒密犯的简单的错误，但是真正了解托勒密贡献的人都会对他肃然起敬。托勒密发明了球坐标，定义了包括赤道和零度经线在内的经纬线，他提出了黄道，还发明了弧度制。<br /><br />当然，他最大也是最有争议的发明是地心说。虽然我们知道地球是围绕太阳运动的，但是在当时，从人们的观测出发，很容易得到地球是宇宙中心的结论。从地球上看，行星的运动轨迹是不规则的，托勒密的伟大之处是用四十个小圆套大圆的方法，精确地计算出了所有行星运动的轨迹。（托勒密继承了毕达格拉斯的一些思想，他也认为圆是最完美的几何图形。）托勒密模型的精度之高，让以后所有的科学家惊叹不已。即使今天，我们在计算机的帮助下，也很难解出四十个套在一起的圆的方程。每每想到这里，我都由衷地佩服托勒密。一千五百年来，人们根据他的计算决定农时。但是，经过了一千五百年，托勒密对太阳运动的累积误差，还是差出了一星期。<br /><br /><img border="0" src="http://googlechinablog.com/uploaded_images/Picture1-710974.jpg" style="border: 1px solid;" /><br />地心说的示意图，我国天文学家张衡的浑天地动说其实就是地心说。<br /><br />纠正地心说错误不是靠在托勒密四十个圆的模型上再多套上几个圆，而是进一步探索真理。哥白尼发现，如果以太阳为中心来描述星体的运行，只需要 8-10 个圆，就能计算出一个行星的运动轨迹，他提出了日心说。很遗憾的事，哥白尼正确的假设并没有得到比托勒密更好的结果，哥白尼的模型的误差比托勒密地要大不少。这是教会和当时人们认为哥白尼的学说是邪说的一个原因，所以日心说要想让人心服口服地接受，就得更准确地描述行星运动。<br /><br />完成这一使命的是开普勒。开普勒在所有一流的天文学家中，资质较差，一生中犯了无数低级的错误。但是他有两条别人没有的东西，从他的老师第谷手中继承的大量的、在当时最精确的观测数据，以及运气。开普勒很幸运地发现了行星围绕太阳运转的轨道实际是椭圆形的，这样不需要用多个小圆套大圆，而只要用一个椭圆就能将星体运动规律描述清楚了。只是开普勒的知识和水平不足以解释为什么行星的轨道是椭圆形的。最后是伟大的科学家牛顿用万有引力解释了这个问题。<br /><br />故事到这里似乎可以结束了。但是，许多年后，又有了个小的波澜。天文学家们发现，天王星的实际轨迹和用椭圆模型算出来的不太符合。当然，偷懒的办法是接着用小圆套大圆的方法修正，但是一些严肃的科学家在努力寻找真正的原因。英国的亚当斯和法国的维内尔（Verrier）独立地发现了吸引天王星偏离轨道的海王星。<br /><br />讲座结束前，我和 Google 中国的工程师们一同总结了这么几个结论：<br />１.　一个正确的数学模型应当在形式上是简单的。（托勒密的模型显然太复杂。）<br />２.　一个正确的模型在它开始的时候可能还不如一个精雕细琢过的错误的模型来的准确，但是，如果我们认定大方向是对的，就应该坚持下去。（日心说开始并没有地心说准确。）<br />３.　大量准确的数据对研发很重要。<br />４.　正确的模型也可能受噪音干扰，而显得不准确；这时我们不应该用一种凑合的修正方法来弥补它，而是要找到噪音的根源，这也许能通往重大发现。<br /><br />在网络搜索的研发中，我们在前面提到的单文本词频/逆文本频率指数（TF/IDF) 和网页排名（page rank)都相当于是网络搜索中的&ldquo;椭圆模型&rdquo;，它们都很简单易懂。</div><img src="http://www.cnblogs.com/tuyile006/aggbug/1564802.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564802.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tuyile006/archive/2009/09/11/1564802.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56831/" target="_blank">谷姐瘫痪 发公开信称已遭黑客攻击5天</a><span style="color:gray">(2010-02-10 13:21)</span><br/>· <a href="http://news.cnblogs.com/n/56829/" target="_blank">.NET Reflector即将商业化</a><span style="color:gray">(2010-02-10 13:08)</span><br/>· <a href="http://news.cnblogs.com/n/56828/" target="_blank">暴雪介绍战网新界面</a><span style="color:gray">(2010-02-10 13:03)</span><br/>· <a href="http://news.cnblogs.com/n/56827/" target="_blank">TLS/SSL协议曝漏洞 影响所有版本Windows</a><span style="color:gray">(2010-02-10 12:56)</span><br/>· <a href="http://news.cnblogs.com/n/56826/" target="_blank">YouTube模式遭嫌弃 Hulu模式成视频行业新宠</a><span style="color:gray">(2010-02-10 12:52)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>