<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_陋室铭</title><subtitle type="text">                永远也不要停下学习的脚步(大道至简至易)      </subtitle><id>http://feed.cnblogs.com/blog/u/21762/rss</id><updated>2012-05-25T08:36:55Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/21762/rss"/><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/23/2514220.html</id><title type="text">OAuth</title><summary type="text">OAuth（开放授权）是一个开放标准，允许用户让第三方应用访问该用户在某一网站上存储的私密的资源（如照片，视频，联系人列表），而无需将用户名和密码提供给第三方应用。OAuth允许用户提供一个令牌，而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站（例如，视频编辑网站)在特定的时段（例如，接下来的2小时内）内访问特定的资源（例如仅仅是某一相册中的视频）。这样，OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息，而不需要分享他们的访问许可或他们数据的所有内容。OAuth是OpenID的一个补充，但是完全不同的服务。</summary><published>2012-05-23T01:21:00Z</published><updated>2012-05-23T01:21:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/23/2514220.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/23/2514220.html"/><content type="html">&lt;p&gt;&lt;strong&gt;OAuth&lt;/strong&gt;（开放授权）是一个开放标准，允许用户让第三方应用访问该用户在某一网站上存储的私密的资源（如照片，视频，联系人列表），而无需将用户名和密码提供给第三方应用。&lt;/p&gt;&lt;p&gt;OAuth允许用户提供一个令牌，而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站（例如，视频编辑网站)在特定的时段（例如，接下来的2小时内）内访问特定的资源（例如仅仅是某一相册中的视频）。这样，OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息，而不需要分享他们的访问许可或他们数据的所有内容。&lt;/p&gt;&lt;p&gt;OAuth是OpenID的一个补充，但是完全不同的服务。&lt;/p&gt;&lt;div id="mw-js-message" class="js-messagebox" style="display: none;"&gt;&amp;nbsp;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2514220.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/23/2514220.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/22/2513062.html</id><title type="text">silverlight后台加载本地图片</title><summary type="text">如果是resourceimgPuzzlePic.Source = new BitmapImage(new Uri("AD/AD.png", UriKind.Relative));如果是contentimgPuzzlePic.Source = new BitmapImage(new Uri("/AD/AD.png", UriKind.Relative));差别就是一个/</summary><published>2012-05-22T03:41:00Z</published><updated>2012-05-22T03:41:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/22/2513062.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/22/2513062.html"/><content type="html">&lt;p&gt;如果是resource&lt;br /&gt;imgPuzzlePic.Source = new BitmapImage(new Uri("AD/AD.png", UriKind.Relative));&lt;/p&gt;&lt;p&gt;如果是content&lt;/p&gt;&lt;p&gt;imgPuzzlePic.Source = new BitmapImage(new Uri("/AD/AD.png", UriKind.Relative));&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;差别就是一个/&lt;/p&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2513062.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/22/2513062.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/21/2511142.html</id><title type="text">Windows XPSP3通过网络级身份验证方式连接Windows Server 2008远程桌面</title><summary type="text">远程桌面大大方便了大家的日常管理工作，Windows Server 2008同样秉承这一优秀特性，并引入网络级身份验证（NLA）作为远程桌面连接的默认身份验证方式。网络级身份验证 (NLA) 是一种新的身份验证方法，在您建立所有远程桌面连接之前完成用户身份验证，并出现登录屏幕。 这是最安全的身份验证方法，有助于保护远程计算机避免黑客或恶意软件的攻击。NLA 的优点：1.最初需要较少的远程计算机资源。验证用户之前，远程计算机使用有限的资源，而不是像以前版本那样启动所有远程桌面连接。2.可以通过减少拒绝服务攻击（试图限制或阻止访问 Internet）来帮助提供更高的安全。3.使用远程计算机身份验证</summary><published>2012-05-21T01:25:00Z</published><updated>2012-05-21T01:25:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/21/2511142.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/21/2511142.html"/><content type="html">&lt;div id="app-share-content"&gt;&lt;span style="font-size: small;"&gt;远程桌面大大方便了大家的日常管理工作，Windows Server 2008同样秉承这一优秀特性，并引入网络级身份验证（NLA）作为远程桌面连接的默认身份验证方式。&lt;/span&gt;&lt;p class="para"&gt;&lt;span style="font-size: small;"&gt;网络级身份验证 (NLA) 是一种新的&lt;/span&gt;&lt;a class="glossaryEntryLink" title="查看定义"&gt;&lt;span style="font-size: small;"&gt;身份验证&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;"&gt;方法，在您建立所有远程桌面连接之前完成用户身份验证，并出现登录屏幕。 这是最安全的身份验证方法，有助于保护远程计算机避免黑客或&lt;/span&gt;&lt;a class="glossaryEntryLink" title="查看定义"&gt;&lt;span style="font-size: small;"&gt;恶意软件&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;"&gt;的攻击。NLA 的优点：&lt;/span&gt;&lt;/p&gt;&lt;p class="para"&gt;&lt;span style="font-size: small;"&gt;1.最初需要较少的远程计算机资源。验证用户之前，远程计算机使用有限的资源，而不是像以前版本那样启动所有远程桌面连接。&lt;/span&gt;&lt;/p&gt;&lt;p class="para"&gt;&lt;span style="font-size: small;"&gt;2.可以通过减少拒绝服务攻击（试图限制或阻止访问 Internet）来帮助提供更高的安全。&lt;/span&gt;&lt;/p&gt;&lt;p class="para"&gt;&lt;span style="font-size: small;"&gt;3.使用远程计算机身份验证，从而帮助防止用户连接到设置为恶意目的的远程计算机。&lt;/span&gt;&lt;/p&gt;&lt;p class="para"&gt;&lt;span style="font-size: small;"&gt;查看计算机是否正在运行带 NLA 的远程桌面版本：&lt;/span&gt;&lt;/p&gt;&lt;p class="para"&gt;&lt;span style="font-size: small;"&gt;开始-运行-mstsc，打开&amp;ldquo;远程桌面连接&amp;rdquo;，单击左上角图标选择&amp;ldquo;关于&amp;rdquo;，如下图08是支持网络级别的身份验证的，而XP SP3默认不支持。&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;img class="blogimg" src="http://hiphotos.baidu.com/hneli/pic/item/0c85931738a4b31c4a90a7da.jpg" alt="" border="0" /&gt;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;img class="blogimg" src="http://hiphotos.baidu.com/hneli/pic/item/ed0a06d4713b8d1ca18bb7db.jpg" alt="" border="0" /&gt;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在使用XP通过远程桌面连接Server 2008远程桌面时会收到提示&amp;ldquo;远程计算机需要网络级身份验证，而您的计算机不支持该验证。请联系您的系统管理员或技术支持人员来获得帮助。&amp;rdquo;如下图：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;p&gt;&lt;img class="blogimg" style="width: 580px; height: 103px;" src="http://hiphotos.baidu.com/hneli/pic/item/24681def4dfdadf2ce1b3eb6.jpg" alt="" width="580" height="103" border="0" /&gt;&lt;/p&gt;&lt;p&gt;要使XP通过远程桌面连接Server 2008，有两种办法：&lt;/p&gt;&lt;p&gt;1.修改Server 2008远程桌面连接方式为&amp;ldquo;允许运行任意版本远程桌面的计算机连接（较不安全）&amp;rdquo;。&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;img class="blogimg" src="http://hiphotos.baidu.com/hneli/pic/item/344f22c3d0760048b319a8bb.jpg" alt="" border="0" /&gt;&lt;/p&gt;&lt;p&gt;2.修改XP注册表以支持使用NLA验证方式进行远程桌面连接。&lt;/p&gt;&lt;p&gt;开始-运行-regedit打开注册表编辑器。&lt;/p&gt;&lt;p&gt;定位到以下注册表键值：HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa，双击右侧Security Packages，打开编辑多字符串对话框，在列表中添加 tspkg 。&lt;/p&gt;&lt;p&gt;定位到以下注册表键值：&lt;/p&gt;&lt;p&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders，双击右侧的SecurityProviders，打开编辑字符串对话框，在数值数据框中添加 , credssp.dll ，注意逗号后有一个英文的空格。&lt;/p&gt;&lt;p&gt;修改完成重启即可。&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2511142.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/21/2511142.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510815.html</id><title type="text">WINDOWS 8</title><summary type="text">WINDOWS 8最大的特点是“整合”，整合了PC、互联网和移动互联网。触摸屏的操控、云端的概念、app store、将主流网站的体验搬到系统、将社交网络整合到操作系统都让人眼前一亮。 1、WEB OS的雏形。较多内容放在“云端”。将来可以更好支持移动客户端。方便地整合google，twitter，flick等应用的内容。 2、更加注重社交网络。WIN8自带应用“人脉”，可以整合Google联系人、Twitter、Facebook、MSN通讯录等内容。 3、Metro整合了鼠标操作系统和触摸操作系统。UI很大程度模仿web、安卓或IOS的一些操控体验。 4、系统自带软件同步更新。尤...</summary><published>2012-05-20T13:04:00Z</published><updated>2012-05-20T13:04:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510815.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510815.html"/><content type="html">&lt;div class="t_txt"&gt;&lt;div class="t_txt"&gt;WINDOWS 8最大的特点是&amp;ldquo;整合&amp;rdquo;，整合了PC、互联网和移动互联网。触摸屏的操控、云端的概念、app store、将主流网站的体验搬到系统、将社交网络整合到操作系统都让人眼前一亮。&lt;/div&gt;&lt;div class="t_txt"&gt;1、WEB OS的雏形。较多内容放在&amp;ldquo;云端&amp;rdquo;。将来可以更好支持移动客户端。方便地整合google，twitter，flick等应用的内容。&lt;/div&gt;&lt;div class="t_txt"&gt;2、更加注重社交网络。WIN8自带应用&amp;ldquo;人脉&amp;rdquo;，可以整合Google联系人、Twitter、Facebook、MSN通讯录等内容。&lt;/div&gt;&lt;div class="t_txt"&gt;3、Metro整合了鼠标操作系统和触摸操作系统。UI很大程度模仿web、安卓或IOS的一些操控体验。&lt;/div&gt;&lt;div class="t_txt"&gt;4、系统自带软件同步更新。尤其是加强了与微软其他产品如Bing、Mail，MSN、Xbox、Live的联系。&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2510815.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510815.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510794.html</id><title type="text">经典力学、相对论、量子力学</title><summary type="text">古老的牛顿力学城堡历经岁月磨砺风雨吹打而始终伟大和坚固，从天上的行星到地上的石块，万物都必恭必敬地遵循着它制定的规则，海王星的发现，就是它所取得的最伟大的胜利之一；在光学的方面，新的电磁理论把它的光荣扩大到了整个电磁世界；在热的方面，热力学三大定律、分子运动论和统计热力学灼灼生辉得让人不敢直视。 更令人惊奇的是，这一切都彼此相符而互相包容，形成了一个经典物理的大同盟。经典力学、经典电动力学和经典热力学（加上统计力学）形成了物理世界的三大支柱。它们紧紧地结合在一块儿，构筑起了一座华丽而雄伟的殿堂。 “这个世界所有的基本原理都已经被发现了！只要拥有足够详细的数据，不管是明天的天气还是一...</summary><published>2012-05-20T12:43:00Z</published><updated>2012-05-20T12:43:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510794.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510794.html"/><content type="html">&lt;p&gt;古老的牛顿力学城堡历经岁月磨砺风雨吹打而始终伟大和坚固，从天上的行星到地上的石块，万物都必恭必敬地遵循着它制定的规则，海王星的发现，就是它所取得的最伟大的胜利之一；在光学的方面，新的电磁理论把它的光荣扩大到了整个电磁世界；在热的方面，热力学三大定律、分子运动论和统计热力学灼灼生辉得让人不敢直视。&lt;/p&gt;&lt;p&gt;更令人惊奇的是，这一切都彼此相符而互相包容，形成了一个经典物理的大同盟。经典力学、经典电动力学和经典热力学（加上统计力学）形成了物理世界的三大支柱。它们紧紧地结合在一块儿，构筑起了一座华丽而雄伟的殿堂。&lt;/p&gt;&lt;p&gt;&amp;ldquo;这个世界所有的基本原理都已经被发现了！只要拥有足够详细的数据，不管是明天的天气还是一亿年以后宇宙的形态，人类都可以分毫不差的计算出来！&amp;rdquo;&lt;/p&gt;&lt;p&gt;量子物理学的破坏力是相当惊人的。在概率解释，不确定性原理和互补原理这三大核心原理中，前两者摧毁了经典世界的因果性，互补原理和不确定原理又合力捣毁了世界的客观性和实在性。&lt;/p&gt;&lt;p&gt;天气永远不可能被预知，宇宙也在每一秒都随机呈现出不同的形态&amp;hellip;&amp;hellip; &lt;/p&gt;&lt;p&gt;越是深入学习，越是觉得，不仅真理在远离自己而去，甚至原本客观真实存在的世界都渐渐变得支离破碎。　&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;经典力学等等，其实是从现象上总结世界的规律，量子物理学，应该已经开始从本质上解析这个世界了。所以一个是&amp;ldquo;预测&amp;rdquo;，一个是&amp;ldquo;预言&amp;rdquo;。&lt;/p&gt;&lt;p&gt;翻译成编程思想就是：&lt;/p&gt;&lt;p&gt;经典力学等等：是系统本身的功能，可以通过掌握所有功能&amp;ldquo;预测&amp;rdquo;未来。&lt;/p&gt;&lt;p&gt;量子物理学：源代码，可以通过掌握源代码&amp;ldquo;预言&amp;rdquo;为了，甚至可以直接修改源代码，改变微观概率，来改变世界原本的形态。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2510794.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/20/2510794.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509312.html</id><title type="text">英雄每多屠狗辈，自古侠女出风尘(看黄金大劫案有感)</title><summary type="text">英雄每多屠狗辈，自古侠女出风尘</summary><published>2012-05-19T15:42:00Z</published><updated>2012-05-19T15:42:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509312.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509312.html"/><content type="html">&lt;p&gt;英雄每多屠狗辈，自古侠女出风尘&lt;/p&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2509312.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509312.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509132.html</id><title type="text">展现、通讯、IO</title><summary type="text">应用程序最基础的就是：展现、通讯、IO展现：比如界面呈现，drawing等等通讯：http,tcp/ip,Socket,WCF,Webservices等等IO：输入输出，文件操作，计算机控制等等。而新出一个技术平台，我最喜欢先研究的是通信技术，我认为通信技术清楚了，这个设计结构就清楚了，至于展现和IO其实和其他技术区别不会大，至少结构区别不大。</summary><published>2012-05-19T12:02:00Z</published><updated>2012-05-19T12:02:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509132.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509132.html"/><content type="html">&lt;p&gt;应用程序最基础的就是：展现、通讯、IO&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;展现：比如界面呈现，drawing等等&lt;/p&gt;&lt;p&gt;通讯：http,tcp/ip,Socket,WCF,Webservices等等&lt;/p&gt;&lt;p&gt;IO：输入输出，文件操作，计算机控制等等。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;而新出一个技术平台，我最喜欢先研究的是通信技术，我认为通信技术清楚了，这个设计结构就清楚了，至于展现和IO其实和其他技术区别不会大，至少结构区别不大。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2509132.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509132.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509129.html</id><title type="text">WP7应用开发笔记(5) 通信设计</title><summary type="text">WP7支持的通信方式1. HTTP协议主要是由WebClient或HttpWebRequest两个类提供，直接封装HTTP协议访问Web站点。最常用的通信方式。2. WCFWCF作为MS大力推广的通信方案非常强大，但是到了WP7上就变成了太监，只支持简单的BasicHttpBinding而且还有非常多的限制。3 Socket7.1SDK里新增的通信方式，支持TCP和UDP但只能使用异步的SocketAsyncEventArgs事件方式，也有不少限制。选择通信方式因为同时需要考虑到服务器端的实现，在服务器端尽量精简，最好不要有什么IIS之类大型依赖。对应是服务器端实现方式如下：HTTP协议Htt</summary><published>2012-05-19T11:55:00Z</published><updated>2012-05-19T11:55:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509129.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509129.html"/><content type="html">&lt;div id="cnblogs_post_body"&gt;&lt;p&gt;&lt;strong&gt;WP7支持的通信方式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. HTTP协议&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;主要是由WebClient或HttpWebRequest两个类提供，直接封装HTTP协议访问Web站点。最常用的通信方式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. WCF&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;WCF作为MS大力推广的通信方案非常强大，但是到了WP7上就变成了太监，只支持简单的BasicHttpBinding而且还有非常多的限制。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3 Socket&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;7.1SDK里新增的通信方式，支持TCP和UDP但只能使用异步的SocketAsyncEventArgs事件方式，也有不少限制。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;选择通信方式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;因为同时需要考虑到服务器端的实现，在服务器端尽量精简，最好不要有什么IIS之类大型依赖。&lt;/p&gt;&lt;p&gt;对应是服务器端实现方式如下：&lt;/p&gt;&lt;table style="width: 400px;" border="0" cellspacing="0" cellpadding="2"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td valign="top" width="200"&gt;HTTP协议&lt;/td&gt;&lt;td valign="top" width="200"&gt;HttpListener&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="200"&gt;WCF&lt;/td&gt;&lt;td valign="top" width="200"&gt;Wcf应用程序宿主&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="200"&gt;Socket&lt;/td&gt;&lt;td valign="top" width="200"&gt;Socket&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;由于我使用的是Win7 HttpListener和BasicHttpBinding在监听外网IP时都需要管理员身份验证，这点很不友好，我每次开程序都提示一下，不爽。所以决定使用Socket。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;SOCKET协议选择&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;而Socket分为TCP和UDP，为了稳定选择了有重传功能和回复的TCP（其实UDP也不是什么问题）。&lt;/p&gt;&lt;p&gt;TCP需要3次握手来维持链接，但是按照&amp;ldquo;偶尔连接&amp;rdquo;(Occasionally Connect)的设计准则，我不能让手机一直保持连接，而且断线检查也是个麻烦事。&lt;/p&gt;&lt;p&gt;所以决定采用HTTP1.0类似的短链接方式，就是连上、发一条消息、然后断开的流程（暂时没有回复）&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;应用层消息报文设计&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个程序比较简单设计的报文也很简单，&lt;/p&gt;&lt;p&gt;因为内网传输不需要考虑身份验证，加密、完整性等，而且短链接不会遇到粘包和拆包之类的，真是太轻松了。&lt;/p&gt;&lt;p&gt;报文结构如下&lt;/p&gt;&lt;table style="width: 516px;" border="0" cellspacing="0" cellpadding="2"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td valign="top" width="133"&gt;Length&lt;/td&gt;&lt;td valign="top" width="133"&gt;长度&lt;/td&gt;&lt;td valign="top" width="248"&gt;4字节 int&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="133"&gt;Action&lt;/td&gt;&lt;td valign="top" width="133"&gt;动作&lt;/td&gt;&lt;td valign="top" width="248"&gt;32字节 UTF8编码&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="133"&gt;Context&lt;/td&gt;&lt;td valign="top" width="133"&gt;内容&lt;/td&gt;&lt;td valign="top" width="248"&gt;长度由Length描述 UTF8编码&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Length表示Context的长度，报文本身长度为Length+4+32&lt;/p&gt;&lt;p&gt;Action目前只有&amp;rdquo;TAP&amp;rdquo;按键 一种&lt;/p&gt;&lt;p&gt;Context表示按键的类型 有2种分类&lt;/p&gt;&lt;ul&gt;&lt;li&gt;一种是 Keyboard 直接对应键盘的键名称&lt;/li&gt;&lt;li&gt;另一种是 Media 媒体控制用 包括TogglePlayPause（播放暂停）、Forward（前进）、Backward（后退）IncreaseVolume（提高音量）等&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;表示方式是&amp;ldquo;Media.TogglePlayPause&amp;rdquo;&lt;/p&gt;&lt;p&gt;Media 协议表&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('2bd41a58-b229-48ec-9f1d-985b6ff0a4dc')"&gt;&lt;div id="cnblogs_code_open_2bd41a58-b229-48ec-9f1d-985b6ff0a4dc" class="cnblogs_code_hide"&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; VirtualKeyboard.Contract&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; KeyMethods&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; KeyboardPackage = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Keyboard&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; MediaPackage = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Media&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Keyboard&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; KeyboardPre = KeyboardPackage + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Enter&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Enter = KeyboardPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Enter&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Esc&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Esc = KeyboardPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Esc&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Media&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; MediaPre = MediaPackage + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;  切换播放暂停&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; TogglePlayPause = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;TogglePlayPause&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 快进&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; FastForward = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;FastForward&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 快退&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; FastBackward = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;FastBackward&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 大步快进&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; VeryFastForward = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;VeryFastForward&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 大步快退&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; VeryFastBackward = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;VeryFastBackward&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 前进&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Forward = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Forward&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 前退&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Backward = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Backward&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 提高音量&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; IncreaseVolume = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;IncreaseVolume&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 降低音量&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; DecreaseVolume = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;DecreaseVolume&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 静音&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; MuteVolume = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;MuteVolume&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 上一集&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; PreviousTrack = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;PreviousTrack&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 下一集&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; NextTrack = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;NextTrack &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 停止&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Stop = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Stop&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 全屏&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; FullScreen = MediaPre + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;FullScreen&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;客户端通信代码实现&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('d090f4c1-f4b2-4799-a721-28e61fa311c4')"&gt;&lt;div id="cnblogs_code_open_d090f4c1-f4b2-4799-a721-28e61fa311c4" class="cnblogs_code_hide"&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; SendCommandCompletedEventArgs : EventArgs&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; Success { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;; }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ErrMessage { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Client&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; ActionSize = &lt;span style="color: #800080;"&gt;32&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; BufferSize = &lt;span style="color: #800080;"&gt;1024&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; EventHandler&amp;lt;SendCommandCompletedEventArgs&amp;gt; SendCommandCompleted;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; OnSendCommandCompleted(SendCommandCompletedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            EventHandler&amp;lt;SendCommandCompletedEventArgs&amp;gt; handler = SendCommandCompleted;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (handler != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;) handler(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, e);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; Client()&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; SendCommandAsync(EndPoint endPoint, &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; action, &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; command)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; actionBuffer = Encoding.UTF8.GetBytes(action);&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; contextBuffer = Encoding.UTF8.GetBytes(command);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; bufferSize = contextBuffer.Length + ActionSize + &lt;span style="color: #800080;"&gt;4&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; lengthBuffer = BitConverter.GetBytes(contextBuffer.Length);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; buffer = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt;[BufferSize];&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; offset = &lt;span style="color: #800080;"&gt;0&lt;/span&gt;;&lt;br /&gt;            Array.Copy(lengthBuffer, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;, buffer, offset, lengthBuffer.Length);&lt;br /&gt;            offset += &lt;span style="color: #800080;"&gt;4&lt;/span&gt;;&lt;br /&gt;            Array.Clear(buffer, offset, ActionSize);&lt;br /&gt;            Array.Copy(actionBuffer, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;, buffer, offset, actionBuffer.Length);&lt;br /&gt;            offset += ActionSize;&lt;br /&gt;            Array.Copy(contextBuffer, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;, buffer, offset, contextBuffer.Length);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; socketAsyncEventArgs = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SocketAsyncEventArgs&lt;br /&gt;                                           {&lt;br /&gt;                                               UserToken =&lt;br /&gt;                                                   &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Socket(AddressFamily.InterNetwork, SocketType.Stream,&lt;br /&gt;                                                              ProtocolType.Tcp)&lt;br /&gt;                                           };&lt;br /&gt;            socketAsyncEventArgs.Completed += AsyncCompleted;&lt;br /&gt;            socketAsyncEventArgs.SetBuffer(buffer, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;, bufferSize);&lt;br /&gt;            socketAsyncEventArgs.RemoteEndPoint = endPoint;&lt;br /&gt;            ProcessConnect(socketAsyncEventArgs);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt; Private&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ProcessConnect(SocketAsyncEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; socket = (Socket)e.UserToken;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; willRaiseEvent = socket.ConnectAsync(e);&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!willRaiseEvent)&lt;br /&gt;            {&lt;br /&gt;                ConnectCompleted(e);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ProcessSend(SocketAsyncEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; socket = (Socket)e.UserToken;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; willRaiseEvent = socket.SendAsync(e);&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!willRaiseEvent)&lt;br /&gt;            {&lt;br /&gt;                SendCompleted(e);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; AsyncCompleted(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sender, SocketAsyncEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt; (e.LastOperation)&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; SocketAsyncOperation.Connect:&lt;br /&gt;                    ConnectCompleted(e);&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; SocketAsyncOperation.Send:&lt;br /&gt;                    SendCompleted(e);&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; SocketAsyncOperation.Receive:&lt;br /&gt;                    ReceiveCompleted(e);&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;default&lt;/span&gt;:&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ReceiveCompleted(SocketAsyncEventArgs e)&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ConnectCompleted(SocketAsyncEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (e.SocketError == SocketError.Success)&lt;br /&gt;            {&lt;br /&gt;                ProcessSend(e);&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                OnSendCommandCompleted(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SendCommandCompletedEventArgs { Success = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;, ErrMessage = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;接收器无法连接&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; });&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; SendCompleted(SocketAsyncEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; socket = (Socket)e.UserToken;&lt;br /&gt;            socket.Close();&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (e.SocketError == SocketError.Success)&lt;br /&gt;            {&lt;br /&gt;                OnSendCommandCompleted(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SendCommandCompletedEventArgs { Success = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt; });&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                OnSendCommandCompleted(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SendCommandCompletedEventArgs { Success = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;, ErrMessage = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;发送命令失败&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; });&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    }&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;转自：&lt;a href="http://www.cnblogs.com/kiminozo/archive/2012/01/25/2329384.html"&gt;http://www.cnblogs.com/kiminozo/archive/2012/01/25/2329384.html&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2509129.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/19/2509129.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/18/2508419.html</id><title type="text">你需要权限才能执行此操作</title><summary type="text">想删除一个文件分明是Administrator用户却提示不允许，点击右键安全才发现只有eyeryone权限并且没有修改权限，原来是创建程序为了不允许删除，权限赋少了，把可修改权限给了就可以删除了。打开这个软件的根文件夹，右键，选择属性，在安全选项卡下，找到你的用户名，如果你不知道那个是，干脆所有的用户名都给它打上全部控制的权限，OK。</summary><published>2012-05-18T14:54:00Z</published><updated>2012-05-18T14:54:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/18/2508419.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/18/2508419.html"/><content type="html">&lt;p&gt;想删除一个文件分明是Administrator用户却提示不允许，点击右键安全才发现只有eyeryone权限并且没有修改权限，原来是创建程序为了不允许删除，权限赋少了，把可修改权限给了就可以删除了。&lt;/p&gt;&lt;p&gt;打开这个软件的根文件夹，右键，选择属性，在安全选项卡下，找到你的用户名，如果你不知道那个是，干脆所有的用户名都给它打上全部控制的权限，OK。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2508419.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/18/2508419.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/15/2500841.html</id><title type="text">在ASP.NET中跟踪和恢复大文件下载</title><summary type="text">在Web应用程序中处理大文件下载的问题一直出了名的困难，因此对于大多数站点来说，如果用户的下载被中断了，它们只能说悲哀降临到用户的身上了。但是我们现在不必这样了，因为你可以使自己的ASP.NET应用程序有能力支持可恢复（继续）的大文件下载。使用本文提供的方法的时候，你可以跟踪下载的过程，这样你就可以处理动态建立的文件--而且要达到这个目标根本不需要旧式的ISAPI动态链接库和非受控的（unmanaged）C++代码。 为客户端提供从互联网上下载文件的服务最容易了，对吗？仅仅只需要把可下载的文件复制到你的Web应用程序目录中，发布链接并让IIS完成所有相关的工作。但是，文件服务不应该比脖子上..</summary><published>2012-05-14T18:11:00Z</published><updated>2012-05-14T18:11:00Z</updated><author><name>宏宇</name><uri>http://www.cnblogs.com/cuihongyu3503319/</uri></author><link rel="alternate" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/15/2500841.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/15/2500841.html"/><content type="html">&lt;p&gt;在Web应用程序中处理大文件&lt;a class="akey" href="http://download.sina.com.cn/" target="_blank"&gt;&lt;span style="color: #000000;"&gt;下载&lt;/span&gt;&lt;/a&gt;的问题一直出了名的困难，因此对于大多数站点来说，如果用户的下载被中断了，它们只能说悲哀降临到用户的身上了。但是我们现在不必这样了，因为你可以使自己的ASP.NET应用程序有能力支持可恢复（继续）的大文件下载。使用本文提供的方法的时候，你可以跟踪下载的过程，这样你就可以处理动态建立的文件--而且要达到这个目标根本不需要旧式的ISAPI动态链接库和非受控的（unmanaged）C++代码。 &lt;br /&gt;&lt;br /&gt;为客户端提供从互联网上下载文件的服务最容易了，对吗？仅仅只需要把可下载的文件复制到你的Web应用程序目录中，发布链接并让IIS完成所有相关的工作。但是，文件服务不应该比脖子上的疼痛还要多（还要麻烦），你不希望整个世界都能访问自己的数据，你不希望服务器被数百个静态文件塞满了，你甚至于希望下载临时文件--只有当客户端开始下载后的空闲时间才建立这些文件。&lt;br /&gt;&lt;br /&gt;不幸的是，使用IIS对下载请求的默认的响应是不可能达到这些效果的。因此在一般情况下，为了获得对下载过程的控制权，开发者需要链接到一个定制的.aspx页面，在这个页面中它们检查用户凭证（credential）、建立可以下载的文件并使用下面的代码把该文件推送给客户端：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Response.WriteFile&lt;br /&gt;Response.End()&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;而这就是出现真正麻烦的地方。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;有什么问题？&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;WriteFile方法看起来非常完美，它使文件的二进制数据流向客户端。但是直到最近我们才知道，WriteFile方法是一个出名的内存占用狂，它把整个文件载入服务器的RAM中来提供服务（实际上它甚至于会占用文件两倍大小的空间）。对于大文件，这会引起服务内存问题，并且可能重复ASP.NET过程。但是在2004年6月&lt;a class="akey" href="http://www.microsoft.com/china" target="_blank"&gt;&lt;span style="color: #000000;"&gt;微软&lt;/span&gt;&lt;/a&gt;发布了一个补丁解决了这个问题。这个补丁现在是.NET Framework 1.1补丁包（SP1）的一部分。&lt;br /&gt;&lt;br /&gt;这个补丁引入了TransmitFile方法，它把一个磁盘文件读入到较小的内存缓冲区之后就开始传输该文件。尽管这个方案解决了内存和循环的问题，但是它仍然不能令人满意。你不能控制响应的生命周期。你无法知道下载是否正确地完成了，你没有办法知道下载是否被中断了，并且（如果你建立了临时文件）你也不知道是否应该、以及什么时候可以删除这些文件。更糟的是，如果下载的确失败了，TransmitFile方法又从客户端下次尝试的文件头部开始下载。&lt;br /&gt;&lt;br /&gt;其中一种可能的解决方案--实现后台智能传输服务（BITS）对于多数站点来说是不可行的，因为这会毁掉维持客户端&lt;a class="akey" href="http://tech.sina.com.cn/it/2004-08-19/1131408183.shtml" target="_blank"&gt;&lt;span style="color: #000000;"&gt;浏览器&lt;/span&gt;&lt;/a&gt;和&lt;a class="akey" href="http://tech.sina.com.cn/introduction/focus/pcos.shtml" target="_blank"&gt;&lt;span style="color: #000000;"&gt;操作系统&lt;/span&gt;&lt;/a&gt;独立性而作出的努力。&lt;br /&gt;&lt;br /&gt;令人满意的解决方案的基础还是来自微软用于解决WriteFile引起的内存混乱问题的第一次尝试（见知识库文章812406）。那篇文章演示了智能的大块数据下载过程，它从文件流中读取数据。在服务器把字节块发送给客户端之前，它使用Response.IsClientConnected属性检查客户端是否仍然保持着连接。如果仍然保持连接，它就继续发送流字节，否则就停止，以防止服务器发送不必要的数据。&lt;br /&gt;这就是我们采用的方法，特别是在下载临时文件的时候。在IsClientConnected返回False的情况下，你就知道下载过程被中断了，你应该保存文件；反之，当这个过程成功完成的时候，你就删除临时文件。此外，为了恢复中断了的下载，你需要做的工作是从上次下载尝试过程中客户端连接失败的文件点开始下载。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;HTTP协议和头信息（Header）支持&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;HTTP协议支持可以用于处理被中断下载的头信息。使用少量的HTTP头信息，你可以增强自己的下载过程，使它完全遵循HTTP协议规范。这个规范与ranges一起提供恢复被中断的下载所需要的一切信息。&lt;br /&gt;&lt;br /&gt;下面是它的工作方式。首先，如果服务器支持客户端断点续传，它就在初始的响应中发送Accept-Ranges头信息。服务器还发送一个实体标签（entity tag）头信息（ETag），它包含一个唯一的标识字符串。&lt;br /&gt;&lt;br /&gt;下面的代码显示了IIS发送给客户端的用于响应一个初始下载请求的一些头信息，它向客户端传递了被请求的文件的详细信息。 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;HTTP/1.1 200 OK&lt;br /&gt;Connection: close&lt;br /&gt;Date: Tue, 19 Oct 2004 15:11:23 GMT&lt;br /&gt;Accept-Ranges: bytes&lt;br /&gt;Last-Modified: Sun, 26 Sep 2004 15:52:45 GMT&lt;br /&gt;ETag: "47febb2cfd76c41:2062"&lt;br /&gt;Cache-Control: private&lt;br /&gt;Content-Type: application/x-zip-compressed&lt;br /&gt;Content-Length: 2844011&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;在接收这些头信息之后，如果下载被中断了，IE浏览器在后来的下载请求中会把Etag值和Range头信息发送回服务器。下面的代码显示了尝试恢复被中断下载时IE发送给服务器的一些头信息。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;GET http://192.168.100.100/download.zip HTTP/1.0&lt;br /&gt;Range: bytes=822603-&lt;br /&gt;Unless-Modified-Since: Sun, 26 Sep 2004 15:52:45 GMT&lt;br /&gt;If-Range: "47febb2cfd76c41:2062"&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;这些头信息表明IE缓存了IIS提供的实体标签，并在If-Range头信息中把它发送回服务器了，这是确保下载从准确相同的文件恢复的一种途径。不幸的是，并非所有的浏览器的工作方式都相同。客户端发送的用于验证文件的其它HTTP头信息可能是If-Match、If-Unmodified-Since或者Unless-Modified-Since。很明显，该规范对于客户端&lt;a class="akey" href="http://tech.sina.com.cn/it/2004-08-19/1537408418.shtml" target="_blank"&gt;&lt;span style="color: #000000;"&gt;软件&lt;/span&gt;&lt;/a&gt;必须支持哪些头信息，或者必须使用哪些头信息没有明确的规定。因此，有些客户端根本就没有使用头信息，而IE只使用If-Range和Unless-Modified-Since。你最好用代码检查这些信息。采用这种方式的时候，你的应用程序可以在非常高的层次遵循HTTP规范，并可以使用多种浏览器。Range头信息指明了被请求的字节范围--在例子中它是服务器应该恢复文件流的起始点。&lt;br /&gt;&lt;br /&gt;当IIS接收到恢复下载的请求类型时，它发回包含下面的头信息的响应信息：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;HTTP/1.1 206 Partial Content&lt;br /&gt;Content-Range: bytes 822603-2844010/2844011&lt;br /&gt;Accept-Ranges: bytes&lt;br /&gt;Last-Modified: Sun, 26 Sep 2004 15:52:45 GMT&lt;br /&gt;ETag: "47febb2cfd76c41:2062"&lt;br /&gt;Cache-Control: private&lt;br /&gt;Content-Type: application/x-zip-compressed&lt;br /&gt;Content-Length: 2021408&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;请注意上面的代码与最初的下载请求的HTTP响应有点差别--恢复下载的请求是206而最初下载的请求是200。这表明通过线路传递进来的内容是部分文件。这一次Content-Range头信息指出了被传递字节的精确数量和位置。&lt;br /&gt;&lt;br /&gt;IE对于这些头信息是很挑剔的。如果最初的响应没有包含Etag头信息，IE永远不会尝试恢复下载。我测试过的其它客户端不使用ETag头信息，它们简单得依赖于文件名、请求范围，并使用Last-Modified头信息（如果它们试图验证该文件）。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;深入了解HTTP协议&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;前面的部分中显示的头信息对于使恢复下载的解决方案运行来说是足够的，但是它没有完全覆盖HTTP规范。&lt;br /&gt;&lt;br /&gt;在单个请求中，Range头信息可以询问多个范围，这种特性称为"多部分范围（multipart ranges）"。请不要与分段下载（segmented downloading）混淆，几乎所有的下载工具都使用分段下载来提高下载速度。这些工具声称通过打开两个或多个并发的连接（每个连接请求文件的不同范围）提高了下载速度。&lt;br /&gt;&lt;br /&gt;多部分范围的想法并没有开启多个连接，但是它可以使客户端软件可以在单个请求/响应周期中请求某个文件的最前面的十个和最后面的十个字节。&lt;br /&gt;&lt;br /&gt;诚实地说，我从来都没有找到使用这种特性软件片断。但是我拒绝在代码声明中写入"它并不是完全的HTTP兼容的"。略去这个特性必定会触犯墨菲法则（Murphy's Law）。无论如何，多部分范围还是被用于电子邮件传输中，把头信息、普通文本和附件分开。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;示例代码&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;我们知道了客户端和服务器如何交换头信息以保证可恢复的下载，把这些知识与文件块流的思想结合起来，你就可以给自己的ASP.NET应用程序增加可靠的下载管理能力了。&lt;br /&gt;&lt;br /&gt;获取下载过程的控制权的方法是从客户端截取下载请求、读取头信息并适当地响应。在.NET之前，你必须编写ISAPI（Internet服务器API）应用程序来实现这种功能，但是.NET框架组件提供了一个IHttpHandler接口，在类中实现的时候，它允许你仅仅使用.NET代码就能够截取和处理请求。这意味着你的应用程序对于下载过程有完全控制权和响应性，再也不会涉及或使用IIS的自动化函数。&lt;br /&gt;&lt;br /&gt;示例代码在HttpHandler.vb文件中包含了一个自定义的HttpHandler类（ZIPHandler）。ZipHandler实现了IhttpHandler接口，并且处理对所有.zip文件的请求。&lt;br /&gt;&lt;br /&gt;为了测试示例代码，你需要在IIS中建立一个新的虚拟目录，并把源文件复制到那儿。在该目录中建立一个叫做download.zip的文件（请注意IIS和ASP.NET不能处理大于2GB的下载，因此要确保你的文件没有超过该限制）。配置你的IIS虚拟目录，通过aspnet_isapi.dll映射.zip扩展名。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;HttpHandler类：ZIPHandler&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;在ASP.NET中映射了.zip扩展名之后，客户端每次向服务器请求.zip文件的时候，IIS调用ZipHandler类的ProcessRequest方法（见下载代码）。&lt;br /&gt;&lt;br /&gt;ProcessRequest方法首先建立自定义的FileInformation类（见下载代码）的一个实例，它封装了下载的状态（例如进行中、被中断了等等）。示例把download.zip示例文件的路径硬编码到代码中了。如果把这段代码应用于你自己的应用程序，需要修改它来打开被请求的文件。 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;' 使用objRequest检测请求了哪个文件，用该文件打开objFile。&lt;br /&gt;' 例如objFile = New Download.FileInformation(&amp;lt;完整文件名&amp;gt;)&lt;br /&gt;objFile = New Download.FileInformation( _&lt;br /&gt;objContext.Server.MapPath("~/download.zip"))&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;接下来，程序使用描述的HTTP头信息（如果请求提供了头信息）执行一系列的验证检查。它把每种检查都封装在小型私有函数中，如果验证成功的话就返回True。如果某个验证检查失败了，响应会立即终止，并发送适当的StatusCode值。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;If Not objRequest.HttpMethod.Equals(HTTP_METHOD_GET) Or Not &lt;br /&gt;objRequest.HttpMethod.Equals(HTTP_METHOD_HEAD) Then&lt;br /&gt;　' 目前只支持GET和HEAD方法&lt;br /&gt;　objResponse.StatusCode = 501 ' 没有执行&lt;br /&gt;ElseIf Not objFile.Exists Then&lt;br /&gt;　' 无法找到被请求的文件&lt;br /&gt;　objResponse.StatusCode = 404 ' 没有找到&lt;br /&gt;ElseIf objFile.Length &amp;gt; Int32.MaxValue Then&lt;br /&gt;　' 文件太大了&lt;br /&gt;　objResponse.StatusCode = 413 ' 请求实体太大&lt;br /&gt;ElseIf Not ParseRequestHeaderRange(objRequest, alRequestedRangesBegin, alRequestedRangesend, _&lt;br /&gt;objFile.Length, bIsRangeRequest) Then&lt;br /&gt;　' Range请求中包含无用的实体&lt;br /&gt;　objResponse.StatusCode = 400 ' 无用的请求&lt;br /&gt;ElseIf Not CheckIfModifiedSince(objRequest,objFile) Then&lt;br /&gt;　' 实体没有被修改过&lt;br /&gt;　objResponse.StatusCode = 304 ' 没有被修改过&lt;br /&gt;ElseIf Not CheckIfUnmodifiedSince(objRequest,objFile) Then&lt;br /&gt;　' 实体在上次被请求的日期之后被修改过 &lt;br /&gt;　objResponse.StatusCode = 412 ' 预处理失败&lt;br /&gt;ElseIf Not CheckIfMatch(objRequest, objFile) Then&lt;br /&gt;　' 实体与请求不匹配&lt;br /&gt;　objResponse.StatusCode = 412 ' 预处理失败&lt;br /&gt;ElseIf Not CheckIfNoneMatch(objRequest, objResponse,objFile) Then&lt;br /&gt;　' 实体的确与none-match请求匹配。&lt;br /&gt;　' 响应代码位于CheckIfNoneMatch函数中&lt;br /&gt;Else&lt;br /&gt;　' 初步检查成功&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;这些初步检查的函数中的ParseRequestHeaderRange（见下载代码）检查客户端是否请求了文件范围（这意味着是一个局部下载）。如果被请求的范围是无效的（无效范围指超越文件大小或包含不合理数字的范围数值），该方法把bIsRangeRequest设置为True。如果请求了范围，CheckIfRange方法会验证IfRange头信息。&lt;br /&gt;&lt;br /&gt;如果被请求的范围是有效的，代码会计算响应信息的大小。如果客户端请求了多个范围，响应信息大小的数值会包含多部分头部信息长度的数值。&lt;br /&gt;&lt;br /&gt;如果不能确定某个发送的头部信息值，程序将把这个下载请求作为最初请求而不是部分下载来处理，从文件的顶部开始发送一个新的下载流。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;If bIsRangeRequest AndAlso CheckIfRange(objRequest, objFile) Then&lt;br /&gt;　' 这是范围请求&lt;br /&gt;　' 如果Range数组包含多个实体，它还是一个多部分范围请求&lt;br /&gt;　bMultipart = CBool(alRequestedRangesBegin.GetUpperBound(0)&amp;gt;0)&lt;br /&gt;　' 进入每个范围来获取整个响应长度 &lt;br /&gt;　For iLoop = alRequestedRangesBegin.GetLowerBound(0) To alRequestedRangesBegin.GetUpperBound(0)&lt;br /&gt;' 内容的长度(这个范围的)&lt;br /&gt;iResponseContentLength += Convert.ToInt32(alRequestedRangesend( _&lt;br /&gt;iLoop) - alRequestedRangesBegin(iLoop)) + 1&lt;br /&gt;If bMultipart Then&lt;br /&gt;　' 如果是多部分范围请求，计算出将发送的中间头信息的长度&lt;br /&gt;　iResponseContentLength += MULTIPART_BOUNDARY.Length&lt;br /&gt;　iResponseContentLength += objFile.ContentType.Length&lt;br /&gt;　iResponseContentLength += alRequestedRangesBegin(iLoop).ToString.Length&lt;br /&gt;　iResponseContentLength += alRequestedRangesend(iLoop).ToString.Length&lt;br /&gt;　iResponseContentLength += objFile.Length.ToString.Length&lt;br /&gt;　' 49是多部分下载中换行和其它必要的字符的长度&lt;br /&gt;　iResponseContentLength += 49&lt;br /&gt;End If&lt;br /&gt;　Next iLoop&lt;br /&gt;&lt;br /&gt;　If bMultipart Then&lt;br /&gt;' 如果是多部分范围请求， &lt;br /&gt;' 我们还必须计算出将发送的最后一个中间头信息的长度&lt;br /&gt;iResponseContentLength +=MULTIPART_BOUNDARY.Length&lt;br /&gt;' 8 是破折号和换行符的长度&lt;br /&gt;iResponseContentLength += 8&lt;br /&gt;　Else&lt;br /&gt;' 不是多部分下载，因此我们必须说明初始HTTP头信息的响应范围&lt;br /&gt;objResponse.AppendHeader( HTTP_HEADER_CONTENT_RANGE, "bytes " &amp;amp; _&lt;br /&gt;alRequestedRangesBegin(0).ToString &amp;amp; "-" &amp;amp; _&lt;br /&gt;alRequestedRangesend(0).ToString &amp;amp; "/" &amp;amp; _&lt;br /&gt;objFile.Length.ToString)&lt;br /&gt;'End If&lt;br /&gt;' 范围响应&lt;br /&gt;objResponse.StatusCode = 206 ' 局部响应&lt;br /&gt;　Else&lt;br /&gt;' 这不是范围请求，或者被请求的范围实体ID与当前的实体ID不匹配， &lt;br /&gt;' 因此开始新的下载&lt;br /&gt;' 指明文件完成部分的大小等于内容的长度 &lt;br /&gt;iResponseContentLength =Convert.ToInt32(objFile.Length)&lt;br /&gt;' 返回正常的OK状态&lt;br /&gt;objResponse.StatusCode = 200&lt;br /&gt;　End If&lt;br /&gt;　' 接下来服务器必须发送几个重要的响应头信息，例如内容长度、Etag、和文件的内容类型：&lt;br /&gt;　' 把内容长度写入响应&lt;br /&gt;　objResponse.AppendHeader( HTTP_HEADER_CONTENT_LENGTH,iResponseContentLength.ToString)&lt;br /&gt;　' 把最后修改日期写入响应&lt;br /&gt;　objResponse.AppendHeader( HTTP_HEADER_LAST_MODIFIED,objFile.LastWriteTimeUTC.ToString("r"))&lt;br /&gt;　' 告诉客户端软件我们接受了范围请求&lt;br /&gt;　objResponse.AppendHeader( HTTP_HEADER_ACCEPT_RANGES,HTTP_HEADER_ACCEPT_RANGES_BYTES)&lt;br /&gt;　' 把文件的实体标签写入响应（用引号括起来）&lt;br /&gt;　objResponse.AppendHeader(HTTP_HEADER_ENTITY_TAG, """" &amp;amp; objFile.EntityTag &amp;amp; """")&lt;br /&gt;　' 把内容类型写入响应 &lt;br /&gt;　If bMultipart Then&lt;br /&gt;' 多部分消息有这种特殊的类型&lt;br /&gt;' 在例子中文件实际的mime类型在以后才写入响应&lt;br /&gt;objResponse.ContentType = MULTIPART_CONTENTTYPE&lt;br /&gt;　Else&lt;br /&gt;' 单个部分消息拥有的文件内容类型&lt;br /&gt;objResponse.ContentType = objFile.ContentType&lt;br /&gt;End If&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;下载所需要的一切都准备好了，可以开始下载文件了。你将使用FileStream对象从文件中读取字节块。把FileInformation实例objFile的State属性设置为fsDownloadInProgress。只要客户端保持连接，服务器就从文件中读取字节块并发送给客户端。对于多部分下载，这段代码会发送特定的头信息。如果客户端中断连接，服务器就把文件状态设置为fsDownloadBroken。如果服务器完成了被请求范围的发送过程，它会把状态设置为fsDownloadFinished（见下载代码）。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;FileInformation辅助类&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;在ZIPHandler部分中你会发现，FileInformation是一个辅助类，它封装了下载状态信息（例如下载中、中断等等）。&lt;br /&gt;&lt;br /&gt;为了建立FileInformation的实例，你需要把被请求文件的路径传递给该类的构造函数：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Public Sub New(ByVal sPath As String)&lt;br /&gt;　m_objFile = New System.IO.FileInfo(sPath)&lt;br /&gt;End Sub&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;FileInformation使用System.IO.FileInfo对象来获取文件的信息，这些信息是作为该对象的属性暴露的（例如文件是否存在、文件全名、大小等等）。这个类还暴露了一个DownloadState枚举，它描述了下载请求的多种状态：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Enum DownloadState&lt;br /&gt;　' Clear：没有下载过程，文件可能在维护&lt;br /&gt;　fsClear = 1&lt;br /&gt;　' Locked：动态建立的文件不能被更改&lt;br /&gt;　fsLocked = 2&lt;br /&gt;　' In Progress：文件被锁定了，下载过程正在进行&lt;br /&gt;　fsDownloadInProgress = 6&lt;br /&gt;　' Broken：文件被锁定了，下载过程正在进行，但是被取消了 &lt;br /&gt;　fsDownloadBroken = 10&lt;br /&gt;　' Finished：文件被锁定了，下载过程完成了&lt;br /&gt;　fsDownloadFinished = 18&lt;br /&gt;End Enum&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;FileInformation还提供了EntityTag属性值。示例代码中的这个值是硬编码的，这是由于示例代码只使用了一个下载文件，并且该文件不会被改变，但是对于实际应用程序来说，你会提供多个文件，甚至于动态地建立文件，你的代码必须为每个文件提供一个唯一的EntityTag值。此外，每次改变或修改该文件的时候，这个值也必须改变。这使客户端软件能够验证它们已经下载的字节块是否仍然是最新的。下面是示例代码中返回硬编码EntityTag值的部分：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Public ReadOnly Property EntityTag() As String&lt;br /&gt;　' EntityTag用于对客户端的初始（200）响应，以及来自客户端的恢复请求 &lt;br /&gt;　Get&lt;br /&gt;' 为文件建立唯一的字符串。&lt;br /&gt;' 注意，只要文件没有发生改变，该唯一码就必须保留。&lt;br /&gt;' 但是，如果文件的确改变了或者被修改了，这个码必须改变。&lt;br /&gt;Return "MyExampleFileID"&lt;br /&gt;　End Get&lt;br /&gt;End Property&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;一个简单的和大致足够安全的EntityTag可能由文件名和文件最后被修改的日期组成。无论使用什么方法，你都必须确保这个值是真的是唯一的，不会与其它文件的EntityTag混淆。我希望在自己的应用程序中按照客户、顾客和邮编索引来动态地替被建立的文件命名，并把用作EntityTag的GUID存储在数据库中。&lt;br /&gt;&lt;br /&gt;ZipFileHandler类读取和设置公共的State属性。在完成下载以后，它把State设置为fsDownloadFinished。这个时候你就可以删除临时文件了。这儿一般需要调用Save方法来维持状态。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Public Property State() As DownloadState&lt;br /&gt;　Get&lt;br /&gt;Return m_nState&lt;br /&gt;　End Get&lt;br /&gt;　Set(ByVal nState As DownloadState)&lt;br /&gt;m_nState = nState&lt;br /&gt;' 可选操作：这个时候你可以自动地删除文件。 &lt;br /&gt;' 如果状态被设置为Finished ，你就再也不需要这个文件了。&lt;br /&gt;' If nState =DownloadState.fsDownloadFinished Then&lt;br /&gt;　' Clear()&lt;br /&gt;' Else&lt;br /&gt;　' Save()&lt;br /&gt;' End If&lt;br /&gt;Save()&lt;br /&gt;　End Set&lt;br /&gt;End Property&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;在文件状态发生改变的任何时候ZipFileHandler都应该调用Save方法，保存文件的状态，这样在以后才能显示给用户。你还可以用它来保存你自己建立的EntityTag。请不要把文件的状态和EntityTag值保存在Application、Session或Cache中--你必须跨越所有的这些这些对象的生命周期来保存信息。 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;table style="width: 90%;" border="1" align="center" bgcolor="#d8d8d1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Private Sub Save()&lt;br /&gt;　' 把该文件下载的状态保存到数据库或XML文件中。&lt;br /&gt;　' 当然，如果你并没有动态地建立文件，就不需要保存这个状态。&lt;br /&gt;End Sub&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;前面提到，示例代码只处理一个已有的文件（download.zip），但是你可以进一步增强这个程序，根据需要建立被请求的文件。&lt;br /&gt;&lt;br /&gt;测试示例代码的时候，你的本地系统或LAN可能太快了，以至于无法中断下载过程，因此我推荐你使用慢速LAN连接（在IIS中减少站点的带宽是一种模拟的方法）或者把服务器放到互联网上。&lt;br /&gt;&lt;br /&gt;在客户端上下载文件仍然很艰难。ISP操作的不对的或配置错误的Web缓冲服务器都可能使大文件下载过程失败，包括下载状况恶化或早期对话终结。如果文件大小超过了255MB，你就应该鼓励顾客使用第三方下载管理软件，尽管某些最新的浏览器内建了基本的下载管理器。&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果你希望进一步扩展示例代码，查阅一下HTTP规范是有益的。你可以为下载建立MD5校验值，使用Content-MD5头信息添加它们，提供一种验证下载文件完整性的途径。示例代码除了GET和HEAD之外没有涉及到其它的HTTP方法。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/cuihongyu3503319/aggbug/2500841.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/cuihongyu3503319/archive/2012/05/15/2500841.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
