<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[牛C网]]></title> 
<link>http://www.niuc.net/index.php</link> 
<description><![CDATA[牛C网提供大量flash/flex/c#等技术资料与实例供您查询！]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[牛C网]]></copyright>
<item>
<link>http://www.niuc.net/post/7923/</link>
<title><![CDATA[SNS洗牌好象悄然开始了！]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 07 Jan 2010 01:41:01 +0000</pubDate> 
<guid>http://www.niuc.net/post/7923/</guid> 
<description>
<![CDATA[ 
	<strong>开心农场要办证</strong><br/><br/>近日，有消息称文化部和新闻出版署将出台措施对社交游戏进行监管成为业内关注的话题。多家知名SNS厂商进入了办证冲刺阶段。 <br/><br/>消息称，2009年12月，新闻出版总署开始出台对SNS游戏实行管理的措施。此前，文化部已将SNS游戏纳入了管理范围。多家知名SNS游戏均表示，早在去年11月份，就已经听说了这则消息，且开始向新闻出版署提交了所有旗下游戏的备案申请。<br/><br/>开发出风靡SNS游戏《开心农场》的上海五分钟COO徐城对媒体表示，出于对知识产权的保护，五分钟早就着手准备文化部许可证和新闻出版署的版号，目前正在等待审批结果。<br/><br/><strong>纳入监管情理中事</strong><br/><br/>此前，对于整个网络游戏行业，文化部和新闻出版署的精力主要放在了大型的在线游戏上。至于SNS中的各类游戏，由于规模小、资金少，尚没有进入监管者的视野。<br/><br/>然而正因为进入门槛较低，随着各类SNS网站如野草般生长开后，引起了监管者的注意。根据文化部规定，<strong>游戏类产品要获得许可证，必须具有千万元以上的注册资金，然而事实上，目前没有一家SNS游戏公司拥有这样的规模。</strong><br/><br/>据知情人士透露，此次文化部还向主要的SNS游戏公司下发了文件，要求凡从事互联网游戏运营业务的，均要办理网络文化经营许可证(含网络游戏)。这同时也显示出文化部的管理思路，即将SNS游戏与普通网游等同，按照同样的标准进行管理。<br/><br/>随着版署的介入，SNS游戏的管理和审核无疑会变得更加严格，知识产权证明、文化部的许可证和新闻出版总署的版号，这些未来将成为SNS游戏上线的“标准配置”。<br/><br/>“虽然SN S游戏的技术含量很低，但是用户很活跃，社会影响力大。”网络游戏独立分析师赵佳雷向记者表示，出于对知识版权的保护，SNS纳入监管是情理中事。<br/><br/><strong>弱肉强食激发差异化营销</strong><br/><br/>将注册资金提升至1000万元以上，对于许多已颇具规模的SNS网站而言并非难事，然而这些公司仅仅处于金字塔的顶端。大多数在风险投资试水下简单运营的SNS公司，是否具备这样的实力，还要看投资者的期待值。如此一来，差异化营销变得更为重要，而SNS网站竞争本身，弱肉强食亦变得愈发明显。<br/><br/>“由于SNS游戏太新颖，缺乏相关的管理规定，导致大家都在观望。”人人网一位SNS负责人向记者表示，目前整个行业的心态都很紧张，但又打听不到确实的消息。目前能做的，只有在通过游戏增加用户粘性的同时，寻找其他方式拉住用户，且为企业客户所认同的营销手段。<br/><br/>据了解，2009年暑期，麦当劳和人人网联手，开展了以“见面吧”为核心创意的营销活动，活动仅持续三个月，就通过线上线下全面互动大幅提升了麦当劳门店的销售额。该负责人称，人人网注重真实注册用户、真实情感交流的氛围以及在年轻群体中强大的影响力，令其成为麦当劳首选营销平台。“未来更为规范的SNS行业，此类营销将成为真正的竞争主体。”<br/><br/><strong>洗牌将进行到底</strong><br/>反看视频网的风风雨雨，从广电出文开办视频服务需要《视听证》后，一直到目前，整个网络开始围绕版权作严打，洗牌是相当彻底，这个过程也改变了中国许多站长的命运。究竟SNS的洗牌是否也会演变成残酷的屠杀呢？只能拭目以待。<br/>Tags - <a href="http://www.niuc.net/tags/sns/" rel="tag">sns</a> , <a href="http://www.niuc.net/tags/%25E5%25BC%2580%25E5%25BF%2583%25E5%2586%259C%25E5%259C%25BA/" rel="tag">开心农场</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7922/</link>
<title><![CDATA[网易或被罚，魔兽世界纷争落地。]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Tue, 05 Jan 2010 01:27:26 +0000</pubDate> 
<guid>http://www.niuc.net/post/7922/</guid> 
<description>
<![CDATA[ 
	风雨飘摇一年多的魔兽国服的问题，可能很快就能得到解决，有消息称：<strong>网易可能会向监管部门支付罚金，从而获准继续运营游戏。而版署和文化部也达成共识，可能会在1月中旬宣布解决方案。</strong><br/><br/>自去年11月以来，网易就一直因为《魔兽世界》的监管问题陷在新闻出版总署和文化部的管辖权纷争中。新闻出版总署以严重违反规定为由，要求网易停止运营《魔兽世界》，但网易因为游戏已经得到文化部的批准而没有执行。<br/><br/>新闻出版总署一位官员周一表示，该机构可能即将发布有关《魔兽世界》的声明。国内媒体上周援引未具名消息人士的话报道说，新闻出版总署和文化部已经就处罚网易一事达成了一致，可能会在1月中旬宣布相关消息。<br/><br/>网易发言人拒绝对市场传言置评。<br/><br/>摩根大通分析师迪克·韦(DickWei)表示：“投资者仍对此事抱着观望的态度，但我认为如果此事能够迅速得到解决，则有利于网易股价走强。”<br/><br/>网易股价已经从去年9月的历史高点回落了23%左右。该公司已经连续两个季度业绩令人失望，而且还面临着来自腾讯和盛大游戏)的强劲挑战。<br/><br/>但分析师认为，一旦《魔兽世界》的监管问题得到解决，网易的股价将得到显著提振。一位不愿具名的分析师预计，此事有望在1个月内得到解决。<br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7921/</link>
<title><![CDATA[严打后新网的域名申请流程]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Tue, 15 Dec 2009 01:18:31 +0000</pubDate> 
<guid>http://www.niuc.net/post/7921/</guid> 
<description>
<![CDATA[ 
	　　根据CNNIC 《<a href="http://www.cnnic.net.cn/html/Dir/2009/12/11/5749.htm" target="_blank">关于进一步加强域名注册信息审核工作的公告</a>》的要求，关于国内域名须提交注册资料以及审核的相关事宜，现紧急通知如下：<br/><br/><strong>一、注册国内域名必须提交资料：</strong><br/><br/>　　注册国内英文域名、国内中文域名时，必须同时提交书面申请资料进行审核。新网互联在初审后递交至CNNIC审核。资料通过CNNIC审核后，域名方能注册成功。未收到书面申请材料的或域名申请材料审核不符合条件的，该域名将予以注销，注册费用将退至您的预付款中。<br/><br/><strong>二、域名注册的流程：</strong><br/><br/><a href="http://www.niuc.net/attachment.php?fid=395" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=395" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong>三、提交资料内容以及方法：</strong><br/><br/>　　1、资料内容：<br/><br/>　　1) 加盖公章的域名注册申请表（原件），可以是扫描件或者数码件电子版，但是必须有红章；<br/>　　2) 企业营业执照或组织机构代码证（副本复印件，上面需盖有效年检章）； <br/>　　<span style="color: #B22222;">提醒：建议在上面注明用途“仅作为申请****域名的凭证”；在网站提交域名注册信息时，请确保单位名称与企业营业执照副本上公司名称或组织机构代码证副本上单位名称一致。</span><br/>　　3) 注册联系人身份证明（复印件，第二代身份证需要复印正反两面）。 <br/>　　<span style="color: #B22222;">提醒：建议在上面注明用途“仅作为申请****域名的凭证”；在网站提交域名注册信息时，请确保联系人姓名与身份证明上一致。</span><br/><br/>　　2、提交方法：<br/><br/>　　所有客户以及合作伙伴，须将上述资料，按照以下规定提交。<br/><table width="548" border="1" align="center" cellpadding="3" cellspacing="0"><tbody><tr><td width="76" bgcolor="#CC0000"><p align="center">提交时间</p></td><td width="95" bgcolor="#CC0000"><p align="center">资料形式</p></td><td width="76" bgcolor="#CC0000"><p align="center">提交方法</p></td><td width="132" bgcolor="#CC0000"><p align="center">发送至</p></td><td width="170" bgcolor="#CC0000"><p align="center">提示</p></td></tr><tr><td width="76"><p align="center">申请注册后72小时内</p></td><td width="95"><p align="center">电子版（扫描件或数码相机拍摄）</p></td><td width="76"><p align="center">邮件</p></td><td width="132"><p align="center">hecha@dns.com.cn</p></td><td width="170"><p align="left">若新网互联在72小时内未收到资料或收到后审核未通过，则该域名将予以注销，注册费用将退至预付款中。</p></td></tr></tbody></table><br/><br/><strong>四、其它注意事项：</strong><br/><br/>　　新网互联将资料初审后将递交CNNIC审核，资料通过CNNIC审核后，域名方能注册成功，审核期间域名无法解析且无法提交续费。<br/><br/><br/>附：《<a href="http://www.dns.com.cn/main/down_doc.php?doc=ymzcsqb.rar" target="_blank">域名注册申请表</a>》请点击下载。<br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E7%25BD%2591%25E7%25BB%259C%25E4%25B8%25A5%25E6%2589%2593/" rel="tag">网络严打</a> , <a href="http://www.niuc.net/tags/cn%25E5%259F%259F%25E5%2590%258D%25E7%2594%25B3%25E8%25AF%25B7/" rel="tag">cn域名申请</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7920/</link>
<title><![CDATA[留点关于最近网络整顿的资料]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Mon, 14 Dec 2009 08:05:55 +0000</pubDate> 
<guid>http://www.niuc.net/post/7920/</guid> 
<description>
<![CDATA[ 
	某群某人曰：也许2010不是世界末日，但却是中国互联网的末日。<br/><br/>某群某人发图：<a href="http://www.niuc.net/attachment.php?fid=393" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=393" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><a href="http://www.niuc.net/attachment.php?fid=394" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=394" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7919/</link>
<title><![CDATA[解决SQL SERVER 2005日志太大]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[SQL技术]]></category>
<pubDate>Fri, 27 Nov 2009 01:54:32 +0000</pubDate> 
<guid>http://www.niuc.net/post/7919/</guid> 
<description>
<![CDATA[ 
	<strong>方法一：</strong><br/><br/><div class="code">backup log 数据库名 with no_log <br/>go <br/>dbcc shrinkdatabase(数据库名,50) 或者 dbcc shrinkdatabase(数据库名) <br/>go <br/>dbcc shrinkfile(日志文件逻辑名,10) </div><br/><br/>日志逻辑文件请到：数据库－>右键属性－>文件 中有一个_log文件就是日志文件逻辑名<br/><br/><strong>方法二：</strong><br/><br/>1.数据库－>右键属性－>选项--->回复模式：简单<br/><br/>2.收缩数据库和日志<br/><br/>3.数据库－>右键属性－>选项--->回复模式：完整<br/><br/><strong>因为日志在一些异常情况下往往是恢复数据库的重要依据，必须设置为完整。</strong><br/><br/><strong>方法三：</strong><br/><br/>建议先备份你的数据库，然后再决定是否删除日志。<br/><br/>在查询分析器中，使用sp_detach_db分离数据库，然后删除相应的日志文件。回到查询分析器，使用sp_attach_single_file_db附加数据文件，会自动创建一个约500k的日志文件。<br/><br/><strong>方法四：</strong><br/><br/>http://msdn.microsoft.com/zh-cn/library/ms175495.aspx<br/>Tags - <a href="http://www.niuc.net/tags/%25E6%2594%25B6%25E7%25BC%25A9%25E6%2595%25B0%25E6%258D%25AE%25E5%25BA%2593/" rel="tag">收缩数据库</a> , <a href="http://www.niuc.net/tags/sql/" rel="tag">sql</a> , <a href="http://www.niuc.net/tags/%25E6%2597%25A5%25E5%25BF%2597%25E8%25BF%2587%25E5%25A4%25A7/" rel="tag">日志过大</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7918/</link>
<title><![CDATA[文化部曰：新闻出版总署终止《魔兽世界》审批违反规定]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Wed, 04 Nov 2009 01:35:10 +0000</pubDate> 
<guid>http://www.niuc.net/post/7918/</guid> 
<description>
<![CDATA[ 
	前言：只能小小的曰一句“网易公关做得太好了，他家的事，成了两部门打响口水战的导火线了”！！！<br/><br/>就<a href="http://www.niuc.net/post/7917/" target="_blank">新闻出版总署关于终止《魔兽世界》审批</a>，网易游戏频道联系文化部文化市场司网络文化处处长刘强。刘强称，目前网络游戏相关审批工作属于文化部管辖范围，新闻出版总署仅负责新闻出版物相关审批，因此所谓终止《魔兽世界》审批的说法并不成立。同时，刘强还表示魔兽世界自7月30日以来属于正常运营，该游戏在经过代理权转交之后，并不存在内测和公测一说，目前《魔兽世界》收费运营以及注册新账户均属于合法行为。<br/><br/>网络文化处处长刘强表示，如果这个事情（新闻出版总署关于终止《魔兽世界》审批）属实，版署是违反三定规定的，只有文化部才有权利查处网游市场。<br/><br/>有媒体报道，新闻出版总署发出通知，<a href="新闻出版总署关于终止《魔兽世界》审批" target="_blank">终止《魔兽世界》(燃烧的远征)审批</a>，退回关于引进出版《魔兽世界》的申请。通知要求，网之易公司立即停止违规行为，纠正错误，停止收费和新账号注册。新闻出版总署将视情依法对其作出相应的行政处罚，包括停止其互联网接入服务。<br/><br/>文化部文化市场司网络文化处处长刘强在接受采访时表示，他现在对这件事情还不清楚，如果这个事情属实的话，版署是违反《“三定”》规定的，只有文化部有权利查处网游市场。<br/><br/>上述“三定”文件是指2008年7月，由国务院办公厅分印发的文化部、国家广播电影电视总局、国家新闻出版总署的《“三定”规定》。三定规定中确定文化部也主管网游，而国家新闻出版总署负责对网游进行前置审批。<br/><br/>另有文化部内部人士对新浪科技表示，文化部已经受理了网易魔兽《巫妖王之怒》的审批，目前还没有最后结果，对于此事文化部目前还没有官方表态。<br/><br/><br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7917/</link>
<title><![CDATA[惊世变故：版署为规范行业，以一儆百，终止魔兽世界审批]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Wed, 04 Nov 2009 01:26:16 +0000</pubDate> 
<guid>http://www.niuc.net/post/7917/</guid> 
<description>
<![CDATA[ 
	2009年11月2日，新闻出版总署发出通知，终止《魔兽世界》（燃烧的远征）审批，退回关于引进出版《魔兽世界》的申请，此举造成网易股价周一早盘跌4.1% ，而网易公告称尚未收到版署正式书面文件通知。网易表示《魔兽世界》暂时不会关闭，但公司可能面临巨额罚款。<br/>............<br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7916/</link>
<title><![CDATA[国内优秀的用户体验设计团队博客]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Wed, 28 Oct 2009 05:41:53 +0000</pubDate> 
<guid>http://www.niuc.net/post/7916/</guid> 
<description>
<![CDATA[ 
	他们是互联网巨头背后的幕后英雄，他们的职业既让人羡慕又让人感到好奇，他们是UED设计师，专注研究用户行为和用户体验改进的设计师团体。我对UED的很多理解和知识积累，可以说离不开今天要推荐给大家的几个博客站点，他们为UED行业贡献了很多的能量和宝贵精验。<br/><br/>NO.1 淘宝UED博客 <a href="http://ued.taobao.com/blog/" target="_blank">点击查看</a><br/><br/>淘宝的UED团队风格活泼而阳光，他们用生动的文字和形象的图片记录生活，他们的"碳酸饮料会"总是能够碰撞出很多新奇的想法，了解到这个博客是从他们的招聘专题开始的，现在已经是招聘第三季了，每季做的都很精彩，大家可以在这里感受到“阿里系”公司的气氛……<br/><br/>淘宝UED招聘第三季官方网站：http://ued.taobao.com/job/season3/<br/><br/>No.2 阿里妈妈UED博客 <a href="http://ued.alimama.com/" target="_blank">点击查看</a><br/><br/>阿里妈妈的UED博客团队相对于淘宝而言是成立较晚的，但是偶感觉他们的光芒可绝不亚于淘宝老大哥，他们在博客上分享了一些CSS及前头设计的一些知识，如果你看到他们近期关于博客换肤的那档子事，你就不可小看他们了，真是怎么说都有道理，他们的视觉设计真牛逼啊。另外还要推荐下他们团队近期开发的阿里妈妈广告板制作系统，可视化操作也很出色。<br/><br/>做广告牌用“阿里妈妈广告牌生成器”详情地址：http://banner.alimama.com<br/><br/>No.3 腾讯ISD Webteam博客 <a href="http://webteam.tencent.com/" target="_blank">点击查看</a><br/><br/>腾讯webteam即腾讯互联网业务系统网站组，他们关注于网站产品的体验设计，包括网站的可用性、视觉风格以及网页重构。腾讯ISD Webteam博客设计视觉冲击力很强，先不说用户体验方面的优秀文章，单纯绚丽多彩的前端视觉设计作品都够我们受益的了。<br/><br/>No.4 19楼UED博客 <a href="http://ued.alimama.com/" target="_blank">点击查看</a><br/><br/>19楼做为一个发展迅速本土化强劲的社区网站，其人性化的视觉设计给人们留下了深刻的印象。19楼的UED团队博客更加“务实”一些，比如说他们近期就把整个19楼新版改进和发步的过程分享了出来，还有前期用户调研等等，这让我们更加近一步的了解到UED团队的运作流程，给我们揭开了一层似乎神秘的面纱……<br/><br/>No.5 口碑网UED博客 <a href="http://ued.koubei.com/" target="_blank">点击查看</a><br/><br/>雅虎口碑网的UED团队博客同样是我们学习前端设计和用户体验技巧的好地方，他们的UED主管还是《JavaScript语言精粹》中文版的译作者之一，牛人辈出的地方。<br/><br/>No.6 网易163UED博客 <a href="http://www.ued163.com/" target="_blank">点击查看</a><br/><br/>网易的UED团队博客相比之前推荐的几个UED博客显得沉稳严肃了一点，包括博客的设计风格上也可以看出一些端倪。在内容方面，他们优秀的团队人员还是帮我们解决了很多在前端设计方面的问题，想页面重构方面还有网易的设计理念的同学，也一定不要错过这里。<br/><br/>No.7 腾讯CDC博客 <a href="http://cdc.tencent.com/" target="_blank">点击查看</a><br/><br/>腾讯CDC成立于06年6月18日，全称是Customer Research & User Experience Design Center（即用户研究与体验设计中心），是腾讯的核心部门之一。整个CDC博客可以说是腾讯产品发布的前沿，在这里我们可以看到腾讯旗下众多的产品资讯和体验报告。<br/><br/>No.8 新浪UED博客 <a href="http://blog.sina.com.cn/chinaued" target="_blank">点击查看</a><br/><br/>新浪UED博客团队用"我的团长我的团"的概念将用户体验和UI等团队划归旗下，chinaued部分主要分享了包括门户/SEO/产品策划等各层面的东西。<br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E7%2594%25A8%25E6%2588%25B7%25E4%25BD%2593%25E9%25AA%258C/" rel="tag">用户体验</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/alias/serp/</link>
<title><![CDATA[前端设计之搜索结果页研究]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Wed, 28 Oct 2009 03:38:29 +0000</pubDate> 
<guid>http://www.niuc.net/alias/serp/</guid> 
<description>
<![CDATA[ 
	<strong><span style="font-size: 24px;">前言</span></strong><br/><br/>什么是SERP，随便你怎么叫它，list页面？搜索结果页？列表页？反正都是指经过搜索引擎搜索后见到的结果列表页。<br/><br/>主体结构大致如此。<br/><a href="http://www.niuc.net/attachment.php?fid=361" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=361" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>页面虽然简单，但是可以探讨的话题非常多：<br/><br/><strong>【关于产品本身的话题】</strong><br/><br/>1. list items如何设计？<br/>2. 搜索过滤如何设计？<br/>3. SERP的广告如何做？<br/>4. 产品推荐如何做？<br/>5. 个性化发展方向？<br/><br/><strong>【关于评价标准的话题】</strong><br/><br/>——我们怎么去评价做得好还是不好呢？<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">如何去制定设计目标？<br/>如何讲设计目标量化为数据指标？<br/>这些考核标准是否和用户需求相符？</div></div><br/><br/>具体到产品中的每一个分支都涉及到不同的评价标准，比如搜索结果过滤（国际站叫做refine search，yahoo叫做facet search）。<br/><br/>以用户的点击率与L-D的转化率去评价是否合理呢？<br/><br/>google设计SERP是会考核用户使用时间，初衷是希望用户尽快离开这个页面——因为找到了合适的结果。<br/><br/>但是实际上，这些并不都是设计能够解决的问题，因为用户离开不离开，更多是受到匹配度的影响。<br/><br/>同样，结果足够匹配，用户使用搜索结果过滤的需求就不那么大了，使用率下降，能据此说明搜索结果过滤设计得不好吗？<br/><br/><strong>【关于设计的难点】</strong><br/><br/>这个页面承载了：<br/><br/>1. 更多的商业期望：电子商务网站说白了其实核心功能就是产品发布与检索，这个页面甚至比首页更加重要。网站需要在这个页面做广告来赚钱，需要有更高的转化率……<br/><br/>2. 用户不断增长的需求：<br/><br/>使用搜索引擎多年，用户早已成为中高级search用户，他们满足了基本需求外，发出了更多的声音：<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">你能更聪明懂我吗？ <br/>能更精准化吗？ <br/>能定制搜索结果吗？ <br/>能够快速过滤吗？ <br/>能不用搜索就把我在找的东西推荐给我吗？</div></div><br/><br/>3. 技术限制：<br/><br/>任何想法都需要有技术的支持。search技术无疑是最考验公司实力的。<br/><br/>这就是为什么有时在公司里，search线的UED不得不靠技术、技术部的产品经理驱动。<br/><br/>4. 考核指标的迷茫：间接导致设计方向的迷茫。由于这个页面的至关重要，多人关注，多种意见交汇，又缺乏明确的考核指标，有时设计师就迷失了改进的方向。<br/><br/><strong>那么，我们设计的时的重点应该是什么？</strong><br/><br/>我个人认为有以下几点是需要设计师时刻记在心里的：<br/><br/>1. 不要过多纠结于数据——数据只能反映一部分事实，但是不能反映全部事实，尤其不能反映造成事实的原因。<br/><br/>2. 理解用户的搜索意图——比结果数据更重要的是对用户意图的把握。当然这很难，但是也不是没有渠道，访谈，看搜索日志，进行key words分析等等。<br/><br/>3. 观察并多了解用户的行为——眼动仪测试，用户访谈，可用性测试，直接面对你的用户，比面对一堆数据也许能够帮我们揭示出更多的东西。<br/><br/><strong><span style="font-size: 24px;">个性化如何影响用户行为？</span></strong><br/><br/>为了组织search线的设计师交流会，特地去准备了一些资料。《SERP 2010》是其中一个，但是由于时间关系没有进行讨论。原著是英文报告，我选择了一些章节非常艰难地进行了一些翻译。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=362" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=362" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>Business to Business Survey 2007报告下载：<br/><a href="attachment.php?fid=367">点击这里下载文件</a><br/>报告很长，涉及到几个话题：个性化会影响用户的浏览时间吗？商业目的的客户和非商业目的的客户浏览行为有不同吗？在多种形式内容组合的SERP上，用户行为是怎么样的？<br/><br/>产生于2007年的报告，里面使用了大量的眼动仪测试以及专家访谈，再推荐您下载一下。<br/><br/>我选择了其中一个点：<strong>个性化对用户行为的影响。</strong><br/><br/>左图为非个性化的google SERP, 右图相应的白色框内区域为个性化内容，在报告中指出如何实现个性化，他们会让测试者先用google的账户登录，tracking他们的浏览行为，记录他们访问的网站，借以判断他们的需求——下一步的动作会是什么？<br/><br/>比如，一个网络购买者，他是停留在研究分析对比阶段还是即将购买？这两种用户关注的信息是不同的，因此给个性化设计提供了依据。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=363" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=363" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/>通过眼动仪测试，可以明显看出：<br/><br/>即使个性化条目并不是出现在顶部的黄金位置，还是得到了几乎同等的关注度和点击数。而左边是没有根据用户的行为推荐的相同区域的内容，仅仅得到了少量的关注度，和三个点击数。<br/><br/><strong><span style="font-size: 18px;">用户行为的改变：</span></strong><br/><br/>用户还是F型浏览这个列表页吗？什么是F型浏览<br/><br/>我们看一下图片和个性化是如何改变了通用的用户行为。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=364" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=364" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>在不考虑图片和个性化的基础上，我们预测用户的浏览行为是这样的：<br/><br/>他首先看到最上面的结果（E区域），然后从这里开始线状的浏览。<br/><br/>而事实上，一旦有了图片和个性化的影响，用户F型浏览行为被打乱了。<br/><br/>1. 他首先被图片吸引到(A区域)。<br/><br/>2. 然后这个有图片的条目B区域引起他的注意。<br/><br/>在做了判断后，如果没有下方的个性化内容，我们预测用户会将目光上移到EC区域，再从上到下浏览。<br/><br/>而有了个性化的内容后，由于其相关性，用户的注意力首先被D区域的内容吸引。<br/><br/>下面是有时间线的对比，下面两个是没有图片和个性化内容影响的SERP，上面两张是有图片和个性化内容的SERP.<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=365" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=365" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong><span style="font-size: 18px;">给我们的启示：</span></strong><br/><br/>由于google和其他搜索引擎结果日益丰富化，在相关性和媒体的丰富性上都在进步。原来我们认为的放到顶部的结果一定能够得到关注的假设逐步受到影响，这意味着页面的sponsored links也应该在相关性和视觉方面跟上脚步。<br/><br/><strong>Google SERP 2010：</strong><br/><br/>在报告中，研究人员做了一个设想中的google的搜索结果页在2010年会变成什么样。2007年的设想，我发现2009年的google已经呈现了设想中的一些元素。比如google在会员登录状态下会出现允许用户删除、排序的功能：<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=366" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=366" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>研究人员大胆设想中的GOOGLE SERP的个性化样子：<br/><br/><strong>1. 对于即将要购买的用户</strong><br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=368" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=368" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>A：店铺广告（Sponsored Links）</strong>，根据用户所在地，进行店铺推荐，广告商能够靠此进行效果最好的人群定位。<br/><br/>诚如以上分析，sponsored links开始考虑丰富性的表现，以期用户能够在更加丰富的SERP上关注到。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=369" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=369" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>B.删除的功能</strong>（哈哈，是不是正是现在google在做的），提供给用户更多影响自己的SERP的功能。<br/><br/><strong>C.看更多结果</strong>——由于2010年搜索引擎更精准化，所以首页就不给用户提供过多的选择。用户可以通过单击more results展开一个传统的搜索结果列表页。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=370" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=370" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>D.当用户进行了一个搜索后就会展开一个tab。</strong><br/><br/><strong>E.当地店铺</strong>——整合google地图。<br/><br/><strong>F.搜索过滤</strong><br/><br/><strong>G.online retailer的推广</strong>——给出在线销售该产品的店铺名称和链接，并且有当前产品的价格。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=371" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=371" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>以下是这个页面的眼动仪测试结果：</strong><br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=372" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=372" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>通过上图我们可以看到：<br/><br/>1. 网页搜索页面区域（A）依然占据了绝大多数点击。<br/><br/>2. Shop local区域吸引到了较多的点击和关注。<br/><br/>3. buy it now区域或许是因为位置偏低吸引到了较少的点击。<br/><br/>4. 顶部的搜素过滤吸引到关注和点击。<br/><br/>5. 右栏的广告虽然形式比较丰富，但是关注度和点击率对比其他板块偏低。<br/><br/>研究人员同时做了另外一个个性化的SERP, 针对“尚处在研究和分析阶段”的用户。他们选取了一批根据浏览行为和搜索行为，被定义为在research而不是购买的测试者进行这个页面的测试。<br/><br/>在这个SERP上，针对这批用户，做了一些板块和内容的调整。<br/><br/>比如：在搜索结果里，增加了customer review条目，其他的条目内容也做了个性化处理，偏向于消费者评价网站多过具体的商业网站。<br/><br/>同时在下方的C区域，做了blog的搜索条目。<br/><br/>D区域的google book，SNS的营销工具。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=373" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=373" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>对这个页面的眼动仪测试结果如下：</strong><br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=374" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=374" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>通过上图可以看出：<br/><br/>1. 最热门的区域是Customer Review(消费者评测)。<br/><br/>2. 其次是个性化的关联性条目（B）区域——B区域以上的sponsored links（C）几乎丧失了关注度。<br/><br/>3. buy it now关注度很少，甚至有用户直接越过这个区域去看之下的博客文章。<br/><br/>4. 同样——右侧丰富的内容再一次被忽略掉。<br/><br/><strong><span style="font-size: 24px;">不要被F型浏览忽悠了</span></strong><br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">什么是F型浏览？</span></span></strong><br/>2006年4月，美国长期研究网站可用性的著名网站设计师杰柯柏·尼尔森（<a href="http://www.useit.com/jakob/" target="_blank">Jakob Nielsen</a>）发表了一项《眼球轨迹的研究》报告（原文：<a href="http://www.useit.com/alertbox/reading_pattern.html" target="_blank">F-Shaped Pattern For Reading Web Content</a>）。<br/><br/>报告中提出，大多数情况下浏览者都不由自主的以“Ｆ”形状的模式阅读网页，这种基本恒定的阅读习惯决定了网页呈现F形的关注热度。<br/><br/>研究者用了几种不同的页面做眼动仪测试，得到了3张热度图，用颜色来表示浏览者眼光聚集的热度，分为最热（<span style="color: #FF0000;">红色</span>）、较热（<span style="color: #FFFF00;">黄色</span>）、不热（<span style="color: #0000FF;">蓝色</span>）和基本不关注（<span style="color: #C0C0C0;">灰色</span>）4种。其中图3搜索结果页因SERP中网站标题、网页摘要较宽，第二条线会随之加长，但仍然是F形状。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=375" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=375" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>研究人员这样诠释F型浏览：</strong><br/><br/><strong>第一步：水平移动</strong><br/><br/>浏览者首先在网页最上部形成一个水平浏览轨迹。<br/><br/><strong>第二步：目光下移，短范围水平移动</strong><br/><br/>浏览者会将目光向下移，扫描比上一步短的区域。<br/><br/><strong>第三步：垂直浏览</strong><br/><br/>浏览者完成上两步后，会将目光沿网页左侧垂直扫描；这一步的浏览速度较慢，也较有系统性、条理性。<br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">F型浏览背后的问题</span></span></strong><br/><br/>F型浏览模式这个理论已经推出很久了，我在很多网站和BLOG上也看到过这样的分享。我在思考几个问题：<br/><br/>1. 出现F型浏览模式的原因是什么？它的背后是什么样的用户需求？<br/><br/>2. F型浏览会受到网站内容、用户需求影响而发生改变吗？会出现别的形状吗？<br/><br/>3. F型浏览模式能够给我们什么启示？如何指导我们进行SERP的设计？<br/><br/>带着这些问题，我进行了一些资料的发掘和尝试，进而有了更多的疑问。<br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">什么造成了F型浏览？</span></span></strong><br/><br/>Jakob Nielsen花费的苦心用三种不同的网页进行测试，目的是为了告诉我们，F型浏览在不同的网站上都是通用的，用户的F型浏览行为并不会受到网站内容和设计出现太大的不同。<br/><br/>但是他并未进一步分析出现F型浏览的原因，结果让很多人误认为这真的是一种“不由自主”的行为。<br/><br/>也正因为如此，F型浏览也很容易被看出很多漏洞来。比如：<br/><br/>为什么不是E而是F？因为我们看到很多眼动仪测试的图片F下面并未一只有一个水平浏览线，而是多个。<br/><br/>为什么下面的一个水平浏览线要短于上面的一条，而实际上我们看到的很多眼动仪图片却是下面的水平浏览线要长于上面的一个？<br/><br/>而进一步的研究也发现，当考虑到网页丰富的内容元素，比如图片时，F型浏览很容易就被打破。如图，你能看到一个典型的F吗？<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=376" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=376" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>图2：图片因素对F型浏览的影响</strong></p><br/><br/>那么，研究人员又来补充F型浏览了，他们说，当有了图片元素影响后，用户的浏览行为发生了改变，不再呈现F型浏览，而是出现了一个E字：<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=377" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=377" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/>我想，再这么推下去，还是避免不了漏洞百出，E出来了，F出来了，将来还会有L，I,C，Z……<br/><br/>还是早早透过现象去分析本质，让我们早点接触F型浏览背后的原因更好。<br/><br/>F型浏览背后的研究以及眼动仪确实能够帮助我们发现一些问题，但是F型浏览的理论在很多场合下显得不是很靠谱。不要被F型浏览忽悠，主要是要警惕那些片面理解F型浏览的拿来主义者、理论主义者（F型浏览的英文原文值得好好阅读并思考）。<br/><br/>我认为，F型或者是E型浏览方式，绝对不是无意识的“不由自主”的行为，而是网站内容、设计，用户需求和用户习惯多重因素作用下的结果。<br/><br/>1.用户的习惯：从左向右，从上到下，这也是传统阅读习惯在网络上的延伸。 <br/><br/>2.互联网用户的阅读习惯：有些像我们阅读黄页或者产品目录的方式：快速扫描的方式，捕捉关键点，读短句子，忽视长篇大论——这些是可以有定论的。 <br/><br/>3.用户的需求：这种习惯是如何养成的？我想是因为互联网用户心中有个需求：寻找某个东西。这个东西可能是具体的，比如搜索某个产品。也可能是模糊的，比如浏览新闻网站，我们是想扫描一下看看有没有“激发兴趣”的关键词。当发现这些“关键词”后，我们会阅读更多的辅助信息以帮助决断：这究竟是不是我要找的东西，当发现是的时候，会产生到详情页面的点击，当然发现不是的话，就会继续向下阅读，继续又一次循环。 <br/><br/>4.用户的耐心是有限度的，所以随着扫描的进行，页面长度的拉伸，他们若找不到太多兴趣点，兴趣自然会逐渐消减，因此就可能形成了所谓的F型或者金三角热区。<br/><br/>用户在浏览的时候，大脑里出现了三个词语：也许是，是，否。<br/><br/>当词语是“也许是”的时候，用户水平浏览以获取更多信息，当答案是否时，用户放弃水平浏览，下移阅读下一段或者下一个搜索条目。当答案是是时，一般会产生一个点击。如图所示：<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=378" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=378" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>这是我心中的F型浏览模型：<br/><br/>1.纵向扫描用以对比：信息为第一维度要关注的信息，用户寻找的是最重要而且有差异化的信息，用户扫描的速度非常快。用户对比中会产生“定位”，从而产生水平阅读。 <br/><br/>2.横向阅读用以判断：信息为第二维度信息，信息可以没有差异化，用户会降低扫描的速度以获取更多有用的信息，帮助自己做判断，要不要点击到详情页。 <br/><br/>3.用户的对比需要有差异化的信息,因此当用户做了一次过滤后,原本差异化的信息变为雷同时,F的纵向条开始转移到另外一组信息处，比如在淘宝上搜索mp3，当我经过过滤，筛选出一组均是米奇的MP3时，图片的差异化就没有了，我的F纵向直接过渡到标题或者其他信息。<br/><br/>在以下的图片无差异化的list上，我甚至有可能直接将F的纵向浏览转移到价格或者地区上。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=379" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=379" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>因此，我们可以把F型理解得更加宽泛一些，这样就不用去纠结上面一横长还是下面一横长或者是两横中间的距离，当然也不会纠结为何F会有多条水平横线。<br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">非典型性F型浏览——用户需求、网站设计等因素的影响</span></span></strong><br/><br/>上面出现一张掺杂了一张图片的搜索结果页（图2），那么我想，当出现多张图片时，效果又是如何呢？<br/><br/>刚好，这几天我想买个电脑包，去淘宝上搜索电脑包，然后不做任何筛选，直接看搜索到的结果。我有意识观测自己的行为（当然，做研究不用采用我的方式），然后发现：<br/><br/>1. 我首先只看图片——图片能够帮助我快速决断，这个包的颜色、款式、风格是否是我所要寻找的（因此快速出现了一条长长的垂直浏览线）。<br/><br/>2. 当图片满足需求后，我会横向阅读该包的说明（标题）。——如果标题中包含了诸如“二手”，“18寸”等字眼，我就会放弃横向浏览，直接用一个斜线过渡到下一个产品图片。<br/><br/>3. 当快速扫描标题未出现让我say no的字眼时，我将视线落到了价格上。请看倒数第二个红色的包包，图片通过，标题通过，然而价格超出预算，于是我放弃用斜线过渡到下面的产品。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=380" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=380" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>我们假设有一个同样和我在买电脑包的人，假设他不关心颜色，不关心款式，只关心价格（很多做批发的也许是这样的）——那么他一来这个搜索结果页，会不会首先从价格所在的列开始纵向浏览，排除，选择，横向研究并下决策——放弃还是点击？这是完全有可能的。<br/><br/>在电子商务网站上，因为图片大多数是第一选择要素，它有天然的优势能够帮助做选择，因此我们的浏览视线从左上方开始，先纵向再横向，纵向和横向的意图是有着微妙的差异的。这个稍后再说。<br/><br/>我们再看看口碑网，同样设计的搜索结果页的浏览视线：<br/><br/>我，代表着一个普通的来找租房的用户。普通的找租房的用户关心什么？<br/><br/>他第一关心的是<strong>户型和地段</strong>。其次是<strong>价格</strong>。<br/><br/>因此，他的浏览视线即有可能是这样的——<br/><br/>1. 越过了图片先看标题，因为标题一般会包含小区名称，户型等重要因素。 <br/><br/>2. 当标题里有让他say no的字眼时，其他的信息（图片、价格、更多介绍等）统统都会视而不见。快速纵向浏览到下面的列表。<br/> <br/>3. 当标题里有字眼满足需求后，用户会横向扫到价格字眼，做第二次判断。 <br/><br/>4. 当价格超出心理预期时（或过低时），用户放弃此列表，视线出现Z型的下移，下移到下一条列表的标题。 <br/><br/>5. 当价格同时满足期望时，一般会产生一个到详情页面的点击（两个黄色区域）。<br/><br/>在下面的例子中，同样是图片，却仅仅起到一个辅助的作用，当用户通过标题或者价格掌握的信息不足以判断时，才会做为参考因素。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=381" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=381" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong><span style="font-size: 24px;">再看看网站设计，是如何影响用户浏览行为的。</span></strong><br/><br/>而，在以相册方式展示的SERP页面，用户的行为又是怎么样的呢？<br/><br/>比如，在淘宝商城，切换成gallery形式。我的需求是寻找一个双肩的电脑包，图片仍然是第一维度要关注的，因此我的视线很有可能呈现Z状，当我发现了有合适的款式和颜色的包包后，我才会扫描第二维度的信息：价格或者标题等。<br/><br/>但是，我又发现，除非我有意识，才能够保证是一个Z型浏览，大多数情况，我在Gallery形式展示的list上，视线呈现放射状的，散乱的，没有规律的，我也许会被其中的某张图片先吸引到——这张图片也许是居中的而不是左上角的图片，然后再由这张图片开始，向上或者向下浏览。<br/><br/>这种galley的设计，虽然能够突出图片的影响，但是实际上倒并不方便用户做“对比和筛选”，会漏掉一些信息，因此可能会出现上上下下的重复浏览——这也许也是国外主流的电子商务网站没有把这种形式作为主要的list设计的原因，当然，这是我个人的猜测。——如果有机会，我们会利用gallery做一下眼动仪的测试，来验证这个结论。<br/><br/>一个tips是，当以gallery方式呈现产品时，同一行的产品不宜过多。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=382" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=382" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">F型浏览给我的启示</span></span></strong><br/><br/>我认为，F型浏览不是绝对的，也不是无意识的，而是受到网站设计、用户需求、用户习惯多重因素影响。那么，我们的SERP设计，尤其是List items设计，要遵循什么原则呢？<br/><br/>只所以写这篇文章，我也由于近期在项目里遇到了一个问题：<br/><br/>list页面如何承载多种曝光需求？<br/><br/>鉴于这个页面的重要性，很多业务部门都希望能够在list页面做一些曝光，仅一个产品列表而言，有部门希望能够放出公司或者产品的认证信息，有的部门或许觉得没必要让用户点击到详情页，可以放出更多信息，比如公司的联系方式，产品运营方，或许希望list能够包含供应商的更多信息，比如规模，主营产品，设备和加工能力，工艺等。<br/><br/>但是，list一个豆腐块状的大小，怎么能够包含那么多信息呢？<br/><br/>所以，我们需要说服各个业务方：list页面设计的目的不是让用户阅读，做决策，而是快速寻找，定位，判断，而真正的决策是需要用户到了详情页甚至是与供应商联系过才能做出的。list页面的设计目的需要单纯，才不至于顾此失彼，忽略了最主要的目的，堆积了大量的信息，反而降低了用户的浏览、对比、定位的效率。<br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">我们能做什么？</span></span></strong><br/><br/><strong><span style="font-size: 14px;">1. 信息优先级的划分</span></strong><br/><br/>就电子商务网站而言，我认为可以划分三个优先级。<br/><br/>第一步：对比和快速筛选。<br/><br/>第二步：获取更多信息以帮助判断。<br/><br/>第三步：研究并决策——下一步动作或者放弃。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=383" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=383" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>注意：</strong>以上的信息优先级要视网站性质、受众需求而有不同，不能适应任何类型的SERP。比如，同样是电子商务网站，淘宝和alibaba就有很大的不一样。淘宝面向的个人买家，而alibaba.com面向的是全球的批发商、中小型的企业采购。用户类型差异比较大，采购类型差异比较大，因此需求就不一样，关注的信息维度就不一样。<br/><br/>对于批发商来讲，因为一个产品要采购大量，一般也都是来样加工订制，不像是淘宝的现货采购，也比较注重长期的供货关系，因此对单品细节的关注就稍微要偏弱一些，更关心供应商本身的信用、供货能力、主营产品等。<br/><br/>而且，行业不同，采购类型也不一样，关注的信息维度也不一样。上周去上海建材展访谈的客户，都能够明确帮我们确认一个事实：行业特征对于SERP设计的差异化需求凸显。——这个话题以后再说。<br/><br/>Heidi想要表达的意思就是：根据你的网站的用户需求和产品特征，你脑子里需要出现这样一个表格——里面的内容需要调整为最适合的优先级。<br/><br/>如果设计师或者产品经理没有传达出信息优先级的概念，那么市场研究人员很可能提供出一个大杂烩，用户关心什么信息，产品图片，描述，认证，信用，价格，物流，供应商资质…………我知道他们当然什么都关心，但是——在什么阶段关心什么是要区分的。<br/><br/><strong><span style="font-size: 14px;">2. 帮助用户更快完成任务</span></strong><br/><br/>当我们脑子里已经有了这张表，并且和项目组达成共识后——达成共识比较不容易，但是我们可以靠用户调研、访谈、行业研究提供足够的proof来得出一个比较合理的信息优先级，那么剩下的任务就是如何更好表现这些内容。<br/><br/>同样的饺子馅，不同的包法显然能够给用户不同的感官感受，包得不好，不但有碍于观瞻，也极有可能破掉，破坏了一锅汤不说，还进了水，导致饺子没有味道。<br/><br/>既然用户在SERP页面的目标很清晰——找到它！<br/><br/>用户在SERP的任务又是可以被我们预测的——他有三个步骤需要完成（参见表格）<br/><br/>每个任务的目标同样也是相对比较清晰的，那么我们设计的任务就是在每个阶段让他能够更加有效率完成子任务目标。<br/><br/>当然你可以说：那我们干嘛要分成三步呢？既然要简化工作量，干脆让他一步完成不更好吗?<br/><br/>但是事实上，用户的这三步也是一个时间轴，不是在同时存在的需求，而且当我们把所有的信息都同时呈现时，反而会极大降低他完成第一步的效率。<br/><br/>我认为，SERP能够满足前两个级别的需求就可以了，第三步可以放到详情页去完成。<br/><br/><strong>如google的搜索list：</strong><br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=384" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=384" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>想一下：如果标题字数太多，或者没有和下面的描述区分开来，没有做关键词的加粗，是不是会导致用户第一步筛选效率降低？<br/><br/>再对比两个网站的list items：<br/><br/><strong>去哪儿——酒店搜索列表页：</strong><br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=385" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=385" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>口碑网——餐馆搜索列表页：</strong><br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=386" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=386" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>两者相比，我个人认为<strong>去哪儿</strong>的表现要优于<strong>口碑网</strong>。<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">去哪儿信息层级非常明确——地段以及酒店品牌第一维度。 <br/>价格单独成列——非常易于二级筛选。 <br/>图片相对不重要，因此只给出数量和链接。 <br/>给出了非常有帮助做选择的促销信息。</div></div><br/><br/>而口碑网的表现：<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">图片非常不重要，但是仍然占据了黄金位置。<br/>由于标题位于图片上部，用户在纵向浏览时，经常被图片因素干扰，不利于快速浏览。<br/>地图、周边等信息，我认为属于第三优先级，却出现在这里，导致每个item非常复杂。<br/>评论：口碑给出了单个用户的评论，有失客观和公正性，会误导客户。<br/>……</div></div><br/><br/>口碑网可以改善这个List设计，比如，图片提取该店铺的主打食物，但是作为第二优先级，在鼠标触发时再出现，将价格单独成列，将评论数目和星星转移到描述左栏，替代掉单个用户的评论……<br/><br/><strong><span style="font-size: 18px;"><span style="color: #008000;">几个值得尝试的行动：</span></span></strong><br/><br/><strong>1. 信息区块划分</strong>——遵循用户习惯和F型浏览，F型浏览反应了用户的浏览习惯，从上至下，从左至右。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=387" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=387" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>2. 加粗、显化能帮助用户提高效率的关键词或者信息</strong><br/><br/>例如SERP搜索关键词的加粗，主要的目的就是让用户快速抓住字眼，然后判断：这是不是我要找的产品。<br/><br/>另外，降低噪音。上面这张图，个人认为将那个跳动的旺旺图标转移到右下角的位置能够帮助用户提升对图片和标题的浏览对比。<br/><br/>像价格这样的字段，一般来说比较重要（第二优先级），那么处理方式有两种：<br/><br/><strong>单独成列</strong>——用户很容易纵向对比，这也是很多网站的做法。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=388" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=388" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>单独成列的时候，我们可以不对价格进行太多视觉上的强化。<br/><br/>但是若做成不单独的列，就需要着重加粗，以帮助用户纵向快速跳跃式的对比。<br/><br/>——不然，就会是这样的：<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=389" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=389" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/><strong>3. 条目设计的拓展性</strong><br/><br/>很有可能你的三段论会受到产品团队的赞赏，但是他们需要更多的信息表现出来。因此他们并不认为只有前两个优先级的信息才能够被放到SERP页面上，其他的只能到详情页查看。<br/><br/>而且，他们的观点也很有sense：<br/><br/>为什么要用户一个一个点开去判断这到底是不是他要找的东西呢？那不是无效的点击吗？<br/><br/>那么，即使已经有了优先级划分，list items设计还要考虑一定的拓展性——可以不展示，在用户有需求的时候展开。<br/><p align="center"><a href="http://www.niuc.net/attachment.php?fid=390" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=390" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a></p><br/><br/>还有更多行动需要你参与：<br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">提出更多质疑，Heidi个人所得必然有一定的局限性。 <br/>帮Heidi验证结论正确与否：提供范例或者反例。 <br/>分析你所在的网站或者接触过的网站SERP页面的条目设计：是如何划分优先级的，用户如何使用这些优先级的？</div></div><br/><br/><strong><span style="font-size: 18px;">总结：</span></strong><br/>在web应用中，几乎所有的前端设计，都是需要千锤百炼的，用户体验的建设，永远是一门值得每个前端设计人员深入研究的学科。<br/>Tags - <a href="http://www.niuc.net/tags/serp%25E6%2590%259C%25E7%25B4%25A2%25E7%25BB%2593%25E6%259E%259C%25E9%25A1%25B5/" rel="tag">serp搜索结果页</a> , <a href="http://www.niuc.net/tags/f%25E5%259E%258B/" rel="tag">f型</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a> , <a href="http://www.niuc.net/tags/%25E7%2594%25A8%25E6%2588%25B7%25E4%25BD%2593%25E9%25AA%258C/" rel="tag">用户体验</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7914/</link>
<title><![CDATA[垂直栅格系统与渐进式行距研究]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 09:21:08 +0000</pubDate> 
<guid>http://www.niuc.net/post/7914/</guid> 
<description>
<![CDATA[ 
	<strong><span style="font-size: 24px;">准备工作</span></strong><br/>我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。 视觉上来说。栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。<br/><br/>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的——也就是我们的“垂直韵律”。<br/>垂直韵律的就像好比我们手上拿着的线格本子，有着一行行的网格线，安排着垂直方向上的文字排版。“排版中的空间就像是音乐里的节拍. ”音乐的节拍虽然有许多变化,但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏. 这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。<br/><br/>其实，那么，在网页里，垂直韵律应由三个因素控制： <br/>•&nbsp;&nbsp;<strong>字体大小(font-size)</strong> <br/>•&nbsp;&nbsp;<strong>行距(line-height)</strong> <br/>•&nbsp;&nbsp;<strong>间距(margin,padding)</strong> <br/><br/>认真考量这三个因素的值，才能实现垂直韵律。<br/> <br/><strong><span style="font-size: 24px;">开工</span></strong><br/><strong>基础行距</strong><br/>在垂直韵律中，基本的单位是行距。在整个页面上设定一个合适的行距是垂直韵律之所以能够成为韵律的必要条件。这个行距，我们将应用于整个页面的所有文字上，包括正文、标题、侧边栏等。例如，我们现在设定我们的字体大小(css font-size)为12px，行距(css line-height)为18px。(对于中文宋体来说，12px是能够清晰显示的最小字号。为了保证可读性，12px的1.5倍行距就是18px。同时12px/18px也是中文互联网上最常用的字号和行距。)我们在空白页面的垂直方向上以18px为单位做垂直网格，就像我们线格本子上的线条，每条网格线也就是基线的对齐线。接着，我们放上三个段落(12px/18px)作为例子讲解。<br/><a href="http://www.niuc.net/attachment.php?fid=352" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=352" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><span style="color: #FF0000;">以上效果代码如下（保存成HTML即可）</span><br/>[codes=html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br/><html xmlns="http://www.w3.org/1999/xhtml"><br/><head><br/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><br/><title>Demo 1 正文</title><br/><style type="text/css"><br/>body{<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;background-color:#f0f0f0<br/>}<br/>.shortcut{&nbsp;&nbsp;<br/>&nbsp;&nbsp;width:500px;<br/>&nbsp;&nbsp;margin:5px auto;<br/>&nbsp;&nbsp;text-align:right;<br/>}<br/>.gridOn .turnOn{<br/>&nbsp;&nbsp;display:none;<br/>}<br/>.gridOff .turnOff{<br/>&nbsp;&nbsp;display:none;<br/>}<br/>#container{<br/>&nbsp;&nbsp;background-color:#fff;<br/>&nbsp;&nbsp;border:1px solid #ccc;<br/>&nbsp;&nbsp;width:500px;<br/>&nbsp;&nbsp;padding:10px;<br/>&nbsp;&nbsp;margin:10px auto;<br/>}<br/>.gridOn #container{<br/>&nbsp;&nbsp;background:#fff url(18px_bg.png) repeat left 8px;&nbsp;&nbsp;<br/>}<br/>p{<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;margin:0;<br/>}<br/></style><br/></head><br/><body&nbsp;&nbsp;&nbsp;&nbsp;id="bodyWrap" class="gridOn"><br/><div class="shortcut"><br/><a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOff'" class="turnOff">关闭网格</a><br/><a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOn'" class="turnOn">显示网格</a><br/></div><br/><div id="container"><br/><div class="main"><p>去年的时候，青云发表过关于栅格系统的文章 。我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。视觉上来说，栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。</p><br/><p>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的。</p><br/><p>排版学家Robert Bringhurst说：“排版中的空间就像是音乐里的节拍。”音乐的节拍虽然有许多变化，但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏。这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。</p><br/></div><br/></div><br/></body><br/></html>[/codes]<br/><br/><strong>段落间距</strong><br/>段落间加上段间距不但美观,而且容易在视觉上区别各段落。但是要注意的是,垂直韵律最容易被打破的地方就是两个元素在垂直方向上的空白了。所以，为了让下一段的文字内容落在网格内，我们要将段落间距设置为基础的倍数。例如：我们可以设置段前距为9px，段后距为9px，9px+9px=18px；或者设置段前距(css margin-top)为0，段后距(css margin-bottom)为18px；或者段前距和段后距都是18px。这里，我们选取第二种方案，即，设置段前距为0，段后距为18px。图中可以看到，每段段落的文字都落在了格子内。关闭网格可以发现，段落清晰明了，比之前容易阅读多了。<br/><a href="http://www.niuc.net/attachment.php?fid=353" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=353" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><span style="color: #FF0000;">以上效果代码如下（保存成HTML即可）</span><br/>[codes=html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br/><html xmlns="http://www.w3.org/1999/xhtml"><br/><head><br/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><br/><title>Demo 2 段间距</title><br/><style type="text/css"><br/>body{<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;background-color:#f0f0f0<br/>}<br/>.shortcut{&nbsp;&nbsp;<br/>&nbsp;&nbsp;width:500px;<br/>&nbsp;&nbsp;margin:5px auto;<br/>&nbsp;&nbsp;text-align:right;<br/>}<br/>.gridOn .turnOn{<br/>&nbsp;&nbsp;display:none;<br/>}<br/>.gridOff .turnOff{<br/>&nbsp;&nbsp;display:none;<br/>}<br/>#container{<br/>&nbsp;&nbsp;background-color:#fff;<br/>&nbsp;&nbsp;border:1px solid #ccc;<br/>&nbsp;&nbsp;width:500px;<br/>&nbsp;&nbsp;padding:10px;<br/>&nbsp;&nbsp;margin:10px auto;<br/>}<br/>.gridOn #container{<br/>&nbsp;&nbsp;background:#fff url(18px_bg.png) repeat left 8px;&nbsp;&nbsp;<br/>}<br/>p{<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;margin-bottom:18px;<br/>&nbsp;&nbsp;text-indent:2em;<br/>}<br/></style><br/></head><br/><body&nbsp;&nbsp;id="bodyWrap" class="gridOn"><br/><div class="shortcut"><br/><a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOff'" class="turnOff">关闭网格</a><br/><a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOn'" class="turnOn">显示网格</a><br/></div><br/><div id="container"><br/><div class="main"><br/><p>去年的时候，青云发表过关于栅格系统的文章 。我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。视觉上来说，栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。</p><br/><p>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的。</p><br/><p>排版学家Robert Bringhurst说：“排版中的空间就像是音乐里的节拍。”音乐的节拍虽然有许多变化，但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏。这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。</p><br/></div><br/></div><br/></body><br/></html>[/codes]<br/><br/><strong>添加标题</strong><br/>使用浏览器默认的样式，你会发现，大多数情况下，垂直韵律都被打破了。所以,添加标题，我们需要选择正确的行距和间距才可以。<br/>有了添加段间距的经验，相信添加标题也不是一件难事了。标题的文字要比正文的文字要大的多。例如，我们现在选择h1的字体大小为24px。<br/><br/>那么，根据附录结论有：<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">行距和全部垂直间距之和为基础行距的倍数。</div></div><br/>那么，我们假设行距为36px，则可以设置段前距为9px，段后距为9px (验证有：36 + 9 + 9 = 54 = 3 * 18)。<br/>同样，我们也可以设置h2：字体大小18px，行高24px，段前距3px，段后距9px(验证有：24 + 3 + 9 = 36 = 2 * 18)。<br/><a href="http://www.niuc.net/attachment.php?fid=354" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=354" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><span style="color: #FF0000;">以上效果代码如下（保存成HTML即可）</span> <br/>[codes=html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br/><html xmlns="http://www.w3.org/1999/xhtml"><br/><head><br/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><br/><title>Demo 3 标题</title><br/><style type="text/css"><br/>body{<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;background-color:#f0f0f0<br/>}<br/>.shortcut{&nbsp;&nbsp;<br/>&nbsp;&nbsp;width:500px;<br/>&nbsp;&nbsp;margin:5px auto;<br/>&nbsp;&nbsp;text-align:right;<br/>}<br/>.gridOn .turnOn{<br/>&nbsp;&nbsp;display:none;<br/>}<br/>.gridOff .turnOff{<br/>&nbsp;&nbsp;display:none;<br/>}<br/>#container{<br/>&nbsp;&nbsp;background-color:#fff;<br/>&nbsp;&nbsp;border:1px solid #ccc;<br/>&nbsp;&nbsp;width:500px;<br/>&nbsp;&nbsp;padding:10px;<br/>&nbsp;&nbsp;margin:10px auto;<br/>}<br/>.gridOn #container{<br/>&nbsp;&nbsp;background:#fff url(18px_bg.png) repeat left 8px;&nbsp;&nbsp;<br/>}<br/>h1{<br/>&nbsp;&nbsp;font-size:24px;<br/>&nbsp;&nbsp;line-height:36px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:9px 0;<br/>}<br/>h2{<br/>&nbsp;&nbsp;font-size:18px;<br/>&nbsp;&nbsp;line-height:24px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:3px 0 9px 0;<br/>}<br/>p{<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;margin-bottom:18px;<br/>&nbsp;&nbsp;text-indent:2em;<br/>}<br/></style><br/></head><br/><body&nbsp;&nbsp;id="bodyWrap" class="gridOn"><br/><div class="shortcut"><br/><a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOff'" class="turnOff">关闭网格</a><br/><a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOn'" class="turnOn">显示网格</a><br/></div><br/><div id="container"><br/><h1>垂直栅格与渐进式行距</h1><br/><div class="main"><br/><p>去年的时候，青云发表过关于栅格系统的文章 。我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。视觉上来说，栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。</p><br/><h2>二级标题</h2><br/><p>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的。</p><br/><p>排版学家Robert Bringhurst说：“排版中的空间就像是音乐里的节拍。”音乐的节拍虽然有许多变化，但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏。这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。</p><br/></div><br/></div><br/></body><br/></html>[/codes]<br/><br/><strong>添加边注 </strong><br/>网站我们常常有侧边栏，我们这里就用右边的边注来代表。在这里的例子中，我们和正文一样设定边注的排版：字体12px，行距18px。正是由于我们前面的努力，我们可以看到，边注的基线和正文的基线是对齐的。关闭网格可以看到，由于基线的对齐，整个排版有条不紊，十分美观。<br/><a href="http://www.niuc.net/attachment.php?fid=355" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=355" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><span style="color: #FF0000;">以上效果代码如下（保存成HTML即可）</span> <br/>[codes=html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br/><html xmlns="http://www.w3.org/1999/xhtml"><br/><head><br/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><br/><title>Demo 4 边注</title><br/><style type="text/css"><br/>body {<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;background-color:#f0f0f0<br/>}<br/>.shortcut {<br/>&nbsp;&nbsp;width:700px;<br/>&nbsp;&nbsp;margin:5px auto;<br/>&nbsp;&nbsp;text-align:right;<br/>}<br/>.gridOn .turnOn {<br/>&nbsp;&nbsp;display:none;<br/>}<br/>.gridOff .turnOff {<br/>&nbsp;&nbsp;display:none;<br/>}<br/>#container {<br/>&nbsp;&nbsp;background-color:#fff;<br/>&nbsp;&nbsp;border:1px solid #ccc;<br/>&nbsp;&nbsp;width:700px;<br/>&nbsp;&nbsp;padding:10px;<br/>&nbsp;&nbsp;margin:10px auto;<br/>}<br/>.gridOn #container {<br/>&nbsp;&nbsp;background:#fff url(18px_bg.png) repeat left 8px;<br/>}<br/>.main {<br/>&nbsp;&nbsp;float:left;<br/>&nbsp;&nbsp;width:490px;<br/>}<br/>.sideNote {<br/>&nbsp;&nbsp;float:right;<br/>&nbsp;&nbsp;width:170px;<br/>&nbsp;&nbsp;text-align:justify;<br/>}<br/>.sideNote p{<br/>&nbsp;&nbsp;text-indent:0;<br/>}<br/>.sideNote p:last-child{<br/>&nbsp;&nbsp;margin-bottom:0;<br/>}<br/>h1{<br/>&nbsp;&nbsp;font-size:24px;<br/>&nbsp;&nbsp;line-height:36px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:9px 0;<br/>}<br/>h2{<br/>&nbsp;&nbsp;font-size:18px;<br/>&nbsp;&nbsp;line-height:24px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:3px 0 9px 0;<br/>}<br/>p {<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;margin-bottom:18px;<br/>&nbsp;&nbsp;text-indent:2em;<br/>}<br/></style><br/></head><br/><body&nbsp;&nbsp;id="bodyWrap" class="gridOn"><br/><div class="shortcut"> <a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOff'" class="turnOff">关闭网格</a> <a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOn'" class="turnOn">显示网格</a> </div><br/><div id="container"><br/>&nbsp;&nbsp;<h1>垂直栅格与渐进式行距</h1><br/>&nbsp;&nbsp;<div class="main"><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>去年的时候，青云发表过关于栅格系统的文章 。我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。视觉上来说，栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。</p><br/>&nbsp;&nbsp;&nbsp;&nbsp;<h2>二级标题</h2><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的。</p><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>排版学家Robert Bringhurst说：“排版中的空间就像是音乐里的节拍。”音乐的节拍虽然有许多变化，但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏。这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。</p><br/>&nbsp;&nbsp;</div><br/>&nbsp;&nbsp;<div class="sideNote"><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>对于中文宋体来说，12px是能够清晰显示的最小字号。为了保证可读性，12px的1.5倍行距就是18px。同时12px/18px也是中文互联网上最常用的字号和行距。</p><br/>&nbsp;&nbsp;</div><br/>&nbsp;&nbsp;<div style="clear:both"></div><br/></div><br/></body><br/></html>[/codes]<br/><br/><strong>添加边框</strong><br/>添加边框道理相同，无非要的就是最后要求基线与网格对齐。这里的例子中，我们来给边注加个边框吧。给他加上1px边框(css border)后，还要再加上8px的补白(css padding)。细心的同学们一定发现了，为什么补白是8px呢？其实很简单，这就是保证垂直方向上的补白和边框之和，是我们的基础行高18px的倍数：垂直方向上两个补白两个边框，那么1 + 8 + 8 + 1 = 18。<br/><a href="http://www.niuc.net/attachment.php?fid=356" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=356" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>加上去后，我们发现，恩？怎么没有右边文字没有对齐到网格上呢？原来加上了补白和边框后，边注下移了9px，所以网格就没有对齐啦。那么，我们就要把边注上移9px。现在，我们可以看到右边的文字已经对齐到网格。是不是感觉不错？<br/><a href="http://www.niuc.net/attachment.php?fid=357" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=357" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><span style="color: #FF0000;">以上效果代码如下（保存成HTML即可）</span> <br/>[codes=html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br/><html xmlns="http://www.w3.org/1999/xhtml"><br/><head><br/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><br/><title>Demo 5 边框</title><br/><style type="text/css"><br/>body {<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;background-color:#f0f0f0<br/>}<br/>.shortcut {<br/>&nbsp;&nbsp;width:700px;<br/>&nbsp;&nbsp;margin:5px auto;<br/>&nbsp;&nbsp;text-align:right;<br/>}<br/>.gridOn .turnOn {<br/>&nbsp;&nbsp;display:none;<br/>}<br/>.gridOff .turnOff {<br/>&nbsp;&nbsp;display:none;<br/>}<br/>#container {<br/>&nbsp;&nbsp;background-color:#fff;<br/>&nbsp;&nbsp;border:1px solid #ccc;<br/>&nbsp;&nbsp;width:700px;<br/>&nbsp;&nbsp;padding:10px;<br/>&nbsp;&nbsp;margin:10px auto;<br/>}<br/>.gridOn #container {<br/>&nbsp;&nbsp;background:#fff url(18px_bg.png) repeat left 8px;<br/>}<br/>.main {<br/>&nbsp;&nbsp;float:left;<br/>&nbsp;&nbsp;width:490px;<br/>}<br/>.sideNote {<br/>&nbsp;&nbsp;float:right;<br/>&nbsp;&nbsp;width:170px;<br/>&nbsp;&nbsp;text-align:justify;<br/>&nbsp;&nbsp;border:1px solid #ccf;<br/>&nbsp;&nbsp;padding:8px;<br/>&nbsp;&nbsp;margin-top:-9px;<br/>}<br/>.sideNote p{<br/>&nbsp;&nbsp;text-indent:0;<br/>}<br/>.sideNote p:last-child{<br/>&nbsp;&nbsp;margin-bottom:0;<br/>}<br/>h1{<br/>&nbsp;&nbsp;font-size:24px;<br/>&nbsp;&nbsp;line-height:36px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:9px 0;<br/>}<br/>h2{<br/>&nbsp;&nbsp;font-size:18px;<br/>&nbsp;&nbsp;line-height:24px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:3px 0 9px 0;<br/>}<br/>p {<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;margin-bottom:18px;<br/>&nbsp;&nbsp;text-indent:2em;<br/>}<br/></style><br/></head><br/><body&nbsp;&nbsp;id="bodyWrap" class="gridOn"><br/><div class="shortcut"> <a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOff'" class="turnOff">关闭网格</a> <a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOn'" class="turnOn">显示网格</a> </div><br/><div id="container"><br/>&nbsp;&nbsp;<h1>垂直栅格与渐进式行距</h1><br/>&nbsp;&nbsp;<div class="main"><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>去年的时候，青云发表过关于栅格系统的文章 。我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。视觉上来说，栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。</p><br/>&nbsp;&nbsp;&nbsp;&nbsp;<h2>二级标题</h2><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的。</p><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>排版学家Robert Bringhurst说：“排版中的空间就像是音乐里的节拍。”音乐的节拍虽然有许多变化，但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏。这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。</p><br/>&nbsp;&nbsp;</div><br/>&nbsp;&nbsp;<div class="sideNote"><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>对于中文宋体来说，12px是能够清晰显示的最小字号。为了保证可读性，12px的1.5倍行距就是18px。同时12px/18px也是中文互联网上最常用的字号和行距。</p><br/>&nbsp;&nbsp;</div><br/>&nbsp;&nbsp;<div style="clear:both"></div><br/></div><br/></body><br/></html>[/codes]<br/><br/><strong><span style="font-size: 24px;">不同字体大小的正文</span></strong><br/>如果有一天，老板告诉你，正文的字体太小啦，他看得眼花。你因此不得不将左边的正文设置成14px大小的字体，右边的边注保持12px。由于正文字体变大，我们也同时加大行距。根据我们前面学到的知识，我重新设计了间距：<br/>•&nbsp;&nbsp;正文：字体大小14px，行距24px，段后距24px <br/>•&nbsp;&nbsp;h1：字体大小24px，行距24px，段前距24px，段后距24px <br/>•&nbsp;&nbsp;h2：字体大小：18px，行距24px，段前距12px，段后距12px <br/>•&nbsp;&nbsp;边注正文：字体大小12px，行距24px，段后距24px <br/>•&nbsp;&nbsp;边注边框：边框粗1px，内补白11px——别忘了还要把它上移12px <br/>效果见:<br/><a href="http://www.niuc.net/attachment.php?fid=358" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=358" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><span style="color: #FF0000;">以上效果代码如下（保存成HTML即可）</span> <br/>[codes=html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br/><html xmlns="http://www.w3.org/1999/xhtml"><br/><head><br/><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><br/><title>Demo 6 不同字体大小的正文</title><br/><style type="text/css"><br/>body {<br/>&nbsp;&nbsp;font-size:12px;<br/>&nbsp;&nbsp;line-height:18px;<br/>&nbsp;&nbsp;background-color:#f0f0f0<br/>}<br/>.shortcut {<br/>&nbsp;&nbsp;width:750px;<br/>&nbsp;&nbsp;margin:5px auto;<br/>&nbsp;&nbsp;text-align:right;<br/>}<br/>.gridOn .turnOn {<br/>&nbsp;&nbsp;display:none;<br/>}<br/>.gridOff .turnOff {<br/>&nbsp;&nbsp;display:none;<br/>}<br/>#container {<br/>&nbsp;&nbsp;background-color:#fff;<br/>&nbsp;&nbsp;border:1px solid #ccc;<br/>&nbsp;&nbsp;width:750px;<br/>&nbsp;&nbsp;padding:10px 20px;<br/>&nbsp;&nbsp;margin:10px auto;<br/>}<br/>.gridOn #container {<br/>&nbsp;&nbsp;background:#fff url(24px_bg.png) repeat left 7px;<br/>}<br/>.main {<br/>&nbsp;&nbsp;float:left;<br/>&nbsp;&nbsp;width:520px;<br/>}<br/>.sideNote {<br/>&nbsp;&nbsp;float:right;<br/>&nbsp;&nbsp;width:170px;<br/>&nbsp;&nbsp;text-align:justify;<br/>&nbsp;&nbsp;border:1px solid #ccf;<br/>&nbsp;&nbsp;padding:11px;<br/>&nbsp;&nbsp;margin-top:-12px;<br/>}<br/>.sideNote p{<br/>&nbsp;&nbsp;text-indent:0;<br/>&nbsp;&nbsp;font-size:12px;<br/>}<br/>.sideNote p:last-child{<br/>&nbsp;&nbsp;margin-bottom:0;<br/>}<br/>h1 {<br/>&nbsp;&nbsp;font-size:24px;<br/>&nbsp;&nbsp;line-height:24px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:24px 0;<br/>}<br/>h2 {<br/>&nbsp;&nbsp;font-size:18px;<br/>&nbsp;&nbsp;line-height:24px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;padding:12px 0 12px 0;<br/>}<br/>p {<br/>&nbsp;&nbsp;font-size:14px;<br/>&nbsp;&nbsp;line-height:24px;<br/>&nbsp;&nbsp;margin:0;<br/>&nbsp;&nbsp;margin-bottom:24px;<br/>&nbsp;&nbsp;text-indent:2em;<br/>&nbsp;&nbsp;color:#333;<br/>}<br/></style><br/></head><br/><body&nbsp;&nbsp;id="bodyWrap" class="gridOn"><br/><div class="shortcut"> <a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOff'" class="turnOff">关闭网格</a> <a href="javascript:void(0)" onclick="document.getElementById('bodyWrap').className='gridOn'" class="turnOn">显示网格</a> </div><br/><div id="container"><br/>&nbsp;&nbsp;<h1>垂直栅格与渐进式行距</h1><br/>&nbsp;&nbsp;<div class="main"><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>去年的时候，青云发表过关于栅格系统的文章 。我们知道网页的栅格系统是运用固定的格子设计版面布局，使其风格工整简洁。视觉上来说，栅格系统能够将大块区域分割成小区域，清楚地展示页面的布局，并能够引导视觉线在各个板块之间扫描、阅读。从信息上来说，栅格系统让信息的呈现方式更加直观，从而有效提高易读性。</p><br/>&nbsp;&nbsp;&nbsp;&nbsp;<h2>二级标题</h2><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>但是大部分栅格系统是在水平方向上的布局，其实，我们的垂直方向也是有栅格系统的。</p><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>排版学家Robert Bringhurst说：“排版中的空间就像是音乐里的节拍。”音乐的节拍虽然有许多变化，但是几乎每首歌都会有一个固定的节拍来掌握整个歌曲的节奏。这就是为什么栅格系统一般用固定宽度的网格阵列来指导和规范网页中的版面布局以及信息分布。</p><br/>&nbsp;&nbsp;</div><br/>&nbsp;&nbsp;<div class="sideNote"><br/>&nbsp;&nbsp;&nbsp;&nbsp;<p>对于中文宋体来说，12px是能够清晰显示的最小字号。为了保证可读性，12px的1.5倍行距就是18px。同时12px/18px也是中文互联网上最常用的字号和行距。</p><br/>&nbsp;&nbsp;</div><br/>&nbsp;&nbsp;<div style="clear:both"></div><br/></div><br/></body><br/></html>[/codes]<br/><br/><strong><span style="font-size: 24px;">完工</span></strong><br/>OK，最后，我们来做个使用前使用后的对比，来张合照吧：<br/>使用前：<br/><a href="http://www.niuc.net/attachment.php?fid=359" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=359" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>使用后：<br/><a href="http://www.niuc.net/attachment.php?fid=360" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=360" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong><span style="font-size: 24px;">附录 基本垂直韵律对行距、间距的要求的推导</span></strong><br/>根据之前的经验,不难得出：<br/>设行距为 dl px ,设垂直方向上的间距和为 ∑ds = dst (段前距) + dsb (段后距) (px) ①,假设基础行距为k px,则<br/>n*k = dl + ∑ds (n为自然数) 即行距和间距之和应当是基础行距的倍数 ②<br/>由方程①、② 得出：<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">•&nbsp;&nbsp;行距和全部垂直间距之和为基础行距的倍数。 </div></div><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E6%25A0%2585%25E6%25A0%25BC%25E7%25B3%25BB%25E7%25BB%259F/" rel="tag">栅格系统</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7911/</link>
<title><![CDATA[网页的水平栅格系统设计]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 07:57:12 +0000</pubDate> 
<guid>http://www.niuc.net/post/7911/</guid> 
<description>
<![CDATA[ 
	<strong>栅格系统的形成</strong><br/>1692年，新登基的法国国王路易十四感到法国的印刷水平强差人意，因此命令成立一个管理印刷的皇家特别委员会。他们的首要任务是设计出科学的、合理的， 重视功能性的新字体。委员会由数学家尼古拉斯加宗（Nicolas Jaugeon）担任领导，他们以罗马体为基础，采用方格为设计依据，每个字体方格分为64个基本方各单位，每个方各单位再分成36个小格，这样，一个印 刷版面就有 2304个小格组成，在这个严谨的几何网格网络中设计字体的形状，版面的编排，试验传达功能的效能，这是是世界上最早对字体和版面进行科学实验的活动，也 是栅格系统最早的雏形。<br/><br/>栅格系统英文为“grid systems”，也有人翻译为“网格系统”，其实是一回事。不过从定义上说，栅格更为准确些，从维基百科查到栅格的定义为：<strong>栅格设计系统（又称网格设计系统、标准尺寸系统、程序版面设计、瑞士平面设计风格、国际主义平面设计风格），是一种平面设计的方法与风格。运用固定的格子设计版面布局，其风格工整简洁，在二战后大受欢迎，已成为今日出版物设计的主流风格之一。</strong><br/><br/><strong>网页设计中的水平栅格系统</strong> <br/>我给网页栅格系统下的定义为：以规则的网格阵列来指导和规范网页中的版面布局以及信息分布。<br/>网页栅格系统是从平面栅格系统中发展而来。对于网页设计来说，栅格系统的使用，不仅可以让网页的信息呈现更加美观易读，更具可用性。而且，对于前端开发来说，网页将更加的灵活与规范。<br/><a href="http://www.niuc.net/attachment.php?fid=346" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=346" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><a href="http://www.niuc.net/attachment.php?fid=347" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=347" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong>栅格系统的设计原理及应用</strong><br/>那么如何设计一个栅格系统？接下来我们将通过实例，详细的介绍一下网页栅格系统的原理与应用：<br/><a href="http://www.niuc.net/attachment.php?fid=348" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=348" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>在网页设计中，我们把宽度为“W”的页面分割成n个网格单元“a”，每个单元与单元之间的间隙设为“i”,此时我们把“a+i”定义“A”。他们之间的关系如下：<br/>W =（a×n）+（n-1）i<br/>由于a+i=A，<br/>可得：<strong>(A×n) – i = W</strong><br/>这个公式表述了网页的布局与网页“背后”的栅格系统之间的某种关系。我们拿yahoo作例，来看一下栅格系统的应用：<br/><a href="http://www.niuc.net/attachment.php?fid=349" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=349" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>yahoo的网站页面宽度为W=950px，每个区块与区块的间隔为i=10px；如果应用上面的公式，可以推出A=40px，既yahoo首页横向版式设计采用的栅格系统为：<br/><strong>（40×n）- 10 = W</strong><br/>下面我们列出当n等于不同数值时W变化的数值表格 ：<br/><a href="http://www.niuc.net/attachment.php?fid=350" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=350" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>从表格可以看出：yahoo首页的布局完全是按照栅格系统进行设计的，每个区块的宽度对应的n值分别为：4，11，9。在这里我们看到一个很有意思 的事情：只要保证一个横向维度的各个区块的n值相加等于24，则即可保证页面的宽度一定是950px。然而，950px的宽度也恰好就是当n=24的时 候，W的宽度值。由此我们得出以下的应用模式：<br/><a href="http://www.niuc.net/attachment.php?fid=351" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=351" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>在栅格系统中，设计师根据需要制定不同的版式或者划分区块，他们的依据将是上面的那张对应表进行设计。这样，一个栅格系统的应用就从此开始了。我们 看到，使用栅格系统的网页设计，非常的有条理性；看上去也很舒服。最重要的是，它给整个网站的页面结构定义了一个标准。对于视觉设计师来说，他们不用再为 设计一个网站每个页面都要想一个宽度或高度而烦恼了。对于前端开发工程师来说，页面的布局设计将完全是规范的和可重用的，这将大大节约了开发成本。对于内 容编辑或广告销售来说，所有的广告都是规则的，通用的，他们再也不用做出一套N张不同尺寸的广告图了……<br/><br/>当然只要你愿意，我们可以衍生出任何一种栅格系统，只要改变A和i的值，这个根据网站的实际情况来制定。那么如何选择合适栅格系统，主要通过“构成 要素与程序、限制与选择、构成要素的比例、组合、虚空间与组合、四边联系与轴的联系、三的法则、圆与构成、水平构成这些设计元素规划，来实现比例和谐的平 面设计”。比较深奥，我们在这里就不详细阐述了。<br/><br/>呵呵，说了一堆栅格系统的优点。大家可能会问：难道栅格系统真的是完美的么？答案是否定的：对于内容信息不确定导致高度不确定的页面，在高度层面上就无法做到栅格了。当然，具体的情况还需具体的分析与解决，这就需要设计师们在实际的应用中不断的总结经验，不断实践了。<br/><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a> , <a href="http://www.niuc.net/tags/%25E6%25A0%2585%25E6%25A0%25BC%25E7%25B3%25BB%25E7%25BB%259F/" rel="tag">栅格系统</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7910/</link>
<title><![CDATA[网站怎样才能粘住用户（以SNS为主作研究）]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 07:47:47 +0000</pubDate> 
<guid>http://www.niuc.net/post/7910/</guid> 
<description>
<![CDATA[ 
	要说国内最能抓住用户的首先要提到的肯定是腾讯的IM，成功坚持十年的成果让其成为用户数量最庞大、有效用户使用率最高的互联网产品。腾讯从简单的OICQ到现在的多维度的QQ家族产业链，<strong>他可以利用把自身的用户群体根据市场需求任意划分成新目标用户群体</strong>，<strong>他们的产品也因为用户群体的多样性从而成为当前产品市场的重要竞争巨头之一</strong>（QQ游戏成功打败边锋，QQ音乐成为各种在线播放平台的领衔角色，QQ邮箱的使用用户也以倍数级地提升，拍拍网和财付通也直逼淘宝和支付宝）。<br/><br/>不能否认腾讯有“青出于蓝而胜于蓝”的能力，但是仅仅是因为做到了交互设计的创新体验吗？在我看来这是个伪命题，<strong>交互设计是让产品发光发亮的工具</strong>，但正因为是工具，被抄袭和模仿的可能性太高（中国人的特点），所以真正让产品成功一定是有自己的核心竞争力。<br/><br/>什么是产品的核心竞争力？简单说就是产品的存活基础，比如肯德基的根本核心竞争力是在中国20年的品牌积累以及它的秘制烹调工艺。<strong>核心竞争力是不可被复制的东西，也是企业在云云众生中脱颖而出的制胜点。</strong><br/><br/>稍微岔开了一下话题，继续谈谈是什么抓住了用户。在我看来，抓住用户的关键其实就是用户本身。<strong>SNS的本质就是聚合，包括内容聚合、技术聚合和用户聚合。</strong>从内容聚合到技术聚合是为SNS构建信息媒介的释放平台，也是让用户聚合的前提。然而用户聚合则是SNS平台更强有力的核心竞争力，它利用用户间点对点的捆绑网络来推动更多的用户加入和使用，简单的讲就是和腾讯IM的模式类似，好友的交流都通过QQ完成，那么更多的好友就自然会使用QQ来进行网络的聚合。一旦用户在平台上搭建起虚拟朋友圈，他需要的内容聚合是更多朋友间的分享，需要的技术聚合是和朋友的更多沟通渠道和方法。虚拟的朋友圈也会给用户带来无形的拉扯力，从而产生抓住用户的粘度。<br/><br/>从目前来看，SNS模式还可以不断地增加其圈子的用户量，但是因为平台各自的核心竞争力还未明显的凸显和区分出来，从内容聚合和技术聚合两方面来讲都比较类似，所以用户的粘度可能未必就只针对于某个平台。想要得到更多用户的青睐，一方面从内容聚合和技术聚合层面上去完善平台应用场景的扩展；另一方面，找到平台和用户的切入点，深层挖掘用户潜在需求以及其社会网络的形成模式，把用户的生活圈尽可能地复制到平台上。<br/><br/>除了SNS以外，其他的<strong>社区型网站的竞争优势主要来自于内容信息的迭代传递</strong>，利用传统的技术方式来完成用户间的沟通问题（例如发帖）。现在这类社区更多形式是以论坛或者推递型网站来表现的，<strong>这类网站的用户忠诚度来自于内容上的满足</strong>，所以更大的问题就是如果失去内容迭代传递的能力，那么相应的用户粘度也会逐渐消失。<strong>我的建议是能够把SNS当作用户聚合的模式，把论坛或者BSP（Blog Service Provider，博客服务托管商）服务形成外围服务模式，把外围服务成为SNS的附加核心竞争力来主导用户的使用习惯。</strong>这一类的SNS+（“SNS+”表示SNS+外围服务核心）比现在的SNS更有目标用户的价值，而且比现在的其他社区型网站有更强的用户聚合能力。简单地说，增加了外围服务的SNS网站把技术聚合和内容聚合更深层次地满足了用户的目标消费，并且促进了用户聚合的速度和粘度。<br/><br/>在我看来，SNS+型的平台就是把现在的SNS模式和外围服务模式结合，把推广平台和用户聚合平台变成以更多实际应用场景为基础的多方聚合的用户使用平台，并且通过创建多种应用场景来把用户生活模式尽可能地复制到平台上来，提高用户的使用粘度、促进用户的成长，通过用户本身牢牢抓住用户。<strong>当然这不是一下子就可以完成的，还需要以一定的会员基数和典型用户群的养成积累为基础才能搭建出新型的SNS+平台。</strong><br/>Tags - <a href="http://www.niuc.net/tags/sns/" rel="tag">sns</a> , <a href="http://www.niuc.net/tags/%25E7%2594%25A8%25E6%2588%25B7%25E7%25B2%2598%25E5%25BA%25A6/" rel="tag">用户粘度</a> , <a href="http://www.niuc.net/tags/seo/" rel="tag">seo</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7909/</link>
<title><![CDATA[关于用户体验中“覆盖率”的研究]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 07:33:19 +0000</pubDate> 
<guid>http://www.niuc.net/post/7909/</guid> 
<description>
<![CDATA[ 
	在用户体验这个行业，经常会听到，<strong>可用性</strong>，<strong>可访问性</strong>这样专业的名词，但是，事实上在很多产品实现过程里都忽略了这一点！WHY？<br/><br/>举个很简单的例子，用户的注册流程，很多交互设计师在做这块流程设计的时候都无可避免的忽略了部分可用性和可访问性，直白点说，产品的应用场景没有覆盖全用户群，损害了这部分用户的可用性和访问性。<br/><br/>太抽象？不明白？好，那我们就用户注册流程展开，侃侃流程中用户提交表单的设计。<br/><a href="http://www.niuc.net/attachment.php?fid=345" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=345" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>看上图，这是现有支付宝注册流程中的一块功能，要实现的功能很简单，个人用户直接填写注册信息，是企业用户的话，就先选择企业，再填写注册信息，最后提交表单，完成操作。流程早就发布上线了，看上去很和谐，但是不然……<br/><br/>不然在哪里呢？应用场景，没错，您答对了。交互设计师在设计这个流程的时候忽略了一些场景，没有考虑到那些客户端对JavaScript不支持或支持不好的用户。做个实验，打开支付宝的注册页面，然后禁用脚本，你会发现，不论怎么搞，你都无法点出企业类的注册信息了！OK，现在明白了吧，企业类的用户在这种场景下基本上就game over了，搞不好还会再来上一句“FT，真TMD难用啊！”<br/><br/>听到这里，或许很多交互设计师坐不住了，“这不是前端开发工程师要去考虑的吗？”，我认为要这样来理解，如果单纯的从前端开发的角度而言，这种实现方式是无可厚非的。什么做法？对的，要说明一下……<br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">实现方案1：采用css样式设置企业注册信息的容器默认为隐藏，当用户点选企业后通过js脚本改变容器的隐藏属性为显示。<br/><br/>实现方案2：通过脚本控制企业注册信息的容器的初始状态为隐藏，当用户点选企业后通过脚本改变容器的隐藏属性为显示。</div></div><br/><br/>一般情况下，前端会有两种实现方案，抛开可访问性，光从Developer这个层面上来选择的话，我选第一种。现在的注册流程中用的也是这个方案。<br/><br/>讨论一下这两个方案吧，各有优缺点，但是今天我们讨论的是可用性和可访问性，所以很显然第一种方案是不可取的。那为什么前端开发工程师还是选择了她呢？自然也有他的道理，如果采用第二种方案的话，势必要在页面结构加载完成后，再去初始化要隐藏的容器，当客户端网速不佳的情况下，会先显示企业注册信息的内容，几秒后又不见了，体验上有所折扣。但是就可用性和可访问性而言，是无懈可击的。假设，当前用户环境禁用了脚本，那么他访问这个页面的时候，企业注册信息不会被隐藏，会显示在当前页面上，易用性可能有一些缺失，但是功能上是可访问可用的，整个流程是健全的。相比两种情况，我想我会选择采用方案2。当然如果你不屑可用可访问性，那就砖头砸我吧！<br/><br/>很多交互设计师都会想当然的认为，类似这样的应用场景受重群体是很小的，也许真实的数据会让你大吃一惊！<strong>总而言之，多为用户想想，是设计师最起码的职业道德！</strong><br/><br/>可用性和可访问性的重要还能表现在很多应用上，如语音阅读器，手机浏览器等，这些在ppk谈javascript中有比较详细的描述，有兴趣的话，可以查阅《ppk谈javascript》。总而言之，语义化的页面结构在以后互联网产品的可用性和可访问性中起着非常重要的作用！<br/><br/>说到这里，我相信看懂的都应该明白可用性和可访问性是咋会事了，除了明白，你是不是也看到了一些问题呢？没错，绝对是有问题的，交互设计和前端开发过程中都存在的问题，专业化路线绝对不是单一的，专业化覆盖的度很重要！<br/>Tags - <a href="http://www.niuc.net/tags/%25E4%25BA%25A4%25E4%25BA%2592%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">交互设计</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E5%25BC%2580%25E5%258F%2591/" rel="tag">前端开发</a> , <a href="http://www.niuc.net/tags/%25E5%258F%25AF%25E7%2594%25A8%25E6%2580%25A7/" rel="tag">可用性</a> , <a href="http://www.niuc.net/tags/%25E5%258F%25AF%25E8%25AE%25BF%25E9%2597%25AE%25E6%2580%25A7/" rel="tag">可访问性</a> , <a href="http://www.niuc.net/tags/%25E7%2594%25A8%25E6%2588%25B7%25E4%25BD%2593%25E9%25AA%258C/" rel="tag">用户体验</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7908/</link>
<title><![CDATA[如何在网页视觉设计中高效合理使用图标]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 07:26:10 +0000</pubDate> 
<guid>http://www.niuc.net/post/7908/</guid> 
<description>
<![CDATA[ 
	在做视觉设计时，如何高效地使用图标是一门学问：该使用什么样的图标？图标该放在哪里？大小如何？图标的使用是否帮助用户更好更快的理解内容，亦或是增加了他们的理解负担甚至产生误导？<br/><br/>为什么使用图标？设计就是传达信息：如果你的网站不能吸引用户，这个问题不在于你分享的信息有多重要、有多刺激。在访问一个网站的最初，大多数用户首先扫描页面来寻找视觉上看着有趣的内容，只有某些事物引起了他们的注意力，他们才真正开始阅读。图标是一个简单、有效的方式吸引用户阅读你网站上的内容。<br/><br/>图标起着与分段一样的心理效果：在视觉上，图标打破了内容，使之不那么让人生却。通过图标将内容划分成几个容易理解的段落和重点，这样的页面很容易阅读，在视觉上也足够有趣以维持用户的注意。因此，不要再浪费时间写那么多无人阅读的内容了，开始使用图标吧！<br/><br/>在本文中，我们将展示<strong>很好的例子和网页设计中使用图标来支持内容的最佳做法。</strong><br/><br/><strong><span style="font-size: 24px;">1.如何使用图标</span></strong><br/>使用图标的首要目标应该是帮助用户更有效地吸收和处理信息。一般的做法是使用大量的空白和那些能增强内容的图标。图标通过给予内容更多的实质和有效的传达，能很好地丰富内容。图标应该用来吸引用户注意信息内容，而不是削弱或取代它。<br/><br/><strong>*让功能清单更有趣</strong><br/><br/>列出服务清单是有效的市场推中实用、必要的一部分，但本质上来说，清单是乏味和无聊的。在您的功能清单中使用图标将使其更具有吸引力。<br/><br/><a href="http://280slides.com/" target="_blank">280 Slides</a><br/><a href="http://www.niuc.net/attachment.php?fid=328" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=328" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>* 吸引用户关注Web应用程序的新功能</strong><br/><br/>图标是一个视觉邀请，吸引用户去试用Web应用程序的最新、最强大的功能。图标应该捕捉用户的注意力，并引导他们到新的功能上。一旦抓住了他们的注意力，告诉他们是什么使得新功能如此伟大。<br/><br/><a href="http://www.panic.com/coda/" target="_blank">Coda</a><br/><a href="http://www.niuc.net/attachment.php?fid=329" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=329" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>*罗列不同的应用和产品</strong><br/><br/>在这种情况下，把图标想成是logo，记住logo的目标是在产品和特定的图像建立精神联系。图标应该独特而简单的：大部分的图标只有128*128像素的，因此要用最低限度的方法，用少表达更多的信息。<br/><br/><a href="http://intridea.com/" target="_blank">intridea</a><br/><a href="http://www.niuc.net/attachment.php?fid=330" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=330" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>* 列出您的服务并增加可读性</strong><br/><br/>图标应与内容相关且设计很简单。考虑您试图表达的内容是什么并在此基础上创建图标。网站或文章的主题是什么？使用什么颜色？是什么风格？现代？经典？在视觉上，图标应与网站整体的内容和个性所传达的思想相统一。<br/><br/><a href="http://jawoodworking.com/information/" target="_blank">j.Alexander Woodworking</a><br/><a href="http://www.niuc.net/attachment.php?fid=331" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=331" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong><span style="font-size: 24px;">2.目的和放置的位置</span></strong><br/>图标的使用让你的网站显得友好、吸引人和专业，这些表明了你注重细节，哪怕这个细节很小很小。让你的图标发挥创意：标题、工具条、功能清单都是放置图标的好地方。<br/><br/>一个很简单的图标能增加网站的魅力和个性。<br/><br/><a href="http://coffeenatic.com/" target="_blank">Coffeenatic</a><br/><a href="http://www.niuc.net/attachment.php?fid=332" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=332" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>* 让用户参与到拥有超长内容的网页中</strong><br/><br/>使用能概括段落大意的图标，这将更便于读者理解文章。<br/><br/><a href="http://www.rackspace.com/index.php" target="_blank">Rackspace</a><br/><a href="http://www.niuc.net/attachment.php?fid=333" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=333" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>在文章的不同章节间使用图标，可以提供视觉注意点来划分这些章节。<br/><br/><a href="http://definedclarity.com/" target="_blank">Defined Clarity</a><br/><a href="http://www.niuc.net/attachment.php?fid=334" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=334" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>* 大小并不重要，即使是小图标也是有效果的</strong><br/><br/>小图标提供的视觉趣味与大图标的相差无异，却不会让用户分心。确保图标容易辨识并和内容紧密相关。<br/><br/><a href="http://morganhayes.com/" target="_blank">Morgan Hayes</a><br/><a href="http://www.niuc.net/attachment.php?fid=335" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=335" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>* 把图标放置在段落的右侧</strong><br/><br/>图标的放置不要局限于常规用法，把图标放在右侧比较少见，因此会更有视觉效果。但是请注意，把图标放置在右侧有时候看起来会显得凌乱。<br/><br/><a href="http://morganhayes.com/" target="_blank">South Creative</a><br/><a href="http://www.niuc.net/attachment.php?fid=336" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=336" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><strong>* 改变图标的大小和位置</strong><br/><br/>发挥创意！改变图标的大小和位置可以让内容更具活力和趣味。<br/><br/><a href="http://mediatemple.net/" target="_blank">Media Temple</a><br/><a href="http://www.niuc.net/attachment.php?fid=337" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=337" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong><span style="font-size: 24px;">3.选择你的风格</span></strong><br/>说到风格，它的目的是让人有深刻印象。如果你期望设计是独特的，那么可以使用新颖的图标，但图标的有效性至关重要。请记住，使用图标是为了增强内容和设计。不要简单地在iStockPhoto上购买看起来很酷的图标，而是要考虑你的网站风格。<br/><br/>同时，图标的匹配性同样重要。把不相匹配的图标放在一起，无论他们单个看起来有多酷，都是个明显的设计错误，非常不专业。以下是一些图标有效地结合于各自网站风格的例子。<br/><br/>使用浅色和很酷的3D设计的图标，提升了网站的外观和感觉。<br/><br/><a href="http://goodbarry.com/" target="_blank">GoodBarry</a><br/><a href="http://www.niuc.net/attachment.php?fid=338" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=338" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>正如下面例子所示的，简洁是有吸引力和实用的。<br/><br/><a href="http://www.crowdspring.com/" target="_blank">CrowdSPRING</a><br/><a href="http://www.niuc.net/attachment.php?fid=339" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=339" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>在2D图标上实用粗糙低劣的风格可以增加很多深度：<br/><br/><a href="http://www.smashingmagazine.com/2009/03/03/how-to-use-icons-to-support-content-in-web-design/" target="_blank">Take the walk</a><br/><a href="http://www.niuc.net/attachment.php?fid=340" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=340" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>选择一个独特和一致的风格，可以使页面有活力且专业：<br/><br/><a href="http://squarespace.com/" target="_blank">Squarespace</a><br/><a href="http://www.niuc.net/attachment.php?fid=341" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=341" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>单色的图标可以帮助突出内容而不会分散注意力：<br/><br/><a href="http://studio7designs.com/" target="_blank">Studio 7Designs</a><br/><a href="http://www.niuc.net/attachment.php?fid=342" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=342" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><a href="http://gist.com/" target="_blank">Gist</a><br/><a href="http://www.niuc.net/attachment.php?fid=343" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=343" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>不要仅仅因为图标看起来很酷而使用它们，选择哪些与你的风格和品牌相符合的图标：<br/><br/><a href="http://gist.com/" target="_blank">Treemo</a><br/><a href="http://www.niuc.net/attachment.php?fid=344" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=344" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>除此之外，还有很多很好的例子，限于篇幅，这里就不一一列举了。如果大家有兴趣，可以查看原文<a href="http://www.smashingmagazine.com/2009/03/03/how-to-use-icons-to-support-content-in-web-design/" target="_blank">How to use icons to support content in Web design</a> 的第四部分-Additional Examples <br/><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a> , <a href="http://www.niuc.net/tags/%25E8%25A7%2586%25E8%25A7%2589%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">视觉设计</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7907/</link>
<title><![CDATA[登陆模块用户反馈信息研究]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 07:07:19 +0000</pubDate> 
<guid>http://www.niuc.net/post/7907/</guid> 
<description>
<![CDATA[ 
	现在很多朋友都不止一个账户，不止一个密码。忘记账户名、密码，或账户名、密码输入错误也就难免啦。每当这个时候，你是否和我一样会有小小的焦虑产生呢？网站给予了什么样的文字帮助，就显得非常重要了。什么样的文字更有助于解决问题，同时也让人觉得舒服？以下我们来做些比较：<br/><br/><strong>一、账户名和密码都没有输入，就点登录</strong><br/><br/>问题分析：这种情况可能出现在新手用户身上，或者忘记账户、侥幸点击登录的情况下<br/><br/>文案关键点：<span style="color: #0000FF;">照顾到新手</span><br/><br/>1. 谷歌<br/><a href="http://www.niuc.net/attachment.php?fid=310" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=310" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>“此时我们无法让您登录到您的帐户”，本来是用户的操作问题，但语气上把问题归因于google自身，是我们无法让您……，而不是您不能……。<br/><br/>2. Uk.match.com<br/><a href="http://www.niuc.net/attachment.php?fid=311" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=311" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>Oops! 是通俗而流行的叹词，适合match偏年轻的用户群。“Please enter”直接提示操作。<br/><br/>3. 豆瓣<br/><a href="http://www.niuc.net/attachment.php?fid=312" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=312" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>这里有一段针对新注册用户的帮助文字“如果你刚刚注册……谢谢你的理解。”重点关注已注册而email未被确认的用户，因为按照规则这些用户尚不能登录，而这可能是他们原来不知道或忽视的问题。<br/> <br/>4. msn中国<br/><a href="http://www.niuc.net/attachment.php?fid=313" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=313" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>最基础的提示，照顾到新手用户，但并不显得罗嗦。<br/><br/><strong>二、密码没有输入，就点登录</strong> <br/><br/>问题分析：这种情况可能出现在新手用户身上，或者忘记密码、侥幸点击登录的情况下；也可能是用户没注意到需要输入密码<br/><br/>文案关键点：<span style="color: #0000FF;">说明问题（没有输入密码）、规则（必须输入密码）或提示操作（输入密码）</span><br/><br/>1. 谷歌<br/><a href="http://www.niuc.net/attachment.php?fid=314" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=314" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a> <br/><br/>2. msn中国<br/><a href="http://www.niuc.net/attachment.php?fid=315" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=315" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>直接说明规则。<br/><br/>3. 百度<br/><a href="http://www.niuc.net/attachment.php?fid=316" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=316" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>如果用户没有输入密码就点击登录，那么这里不会出现任何新的文字提示；也就是说，默认用户自知自己没有输入密码，也清楚没有输入密码就不能登录；系统也就没必要多说什么了。<br/> <br/>4. 淘宝<br/><a href="http://www.niuc.net/attachment.php?fid=317" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=317" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>简短有效的提示，直接说明问题，默认用户知道需要的操作是输入密码。<br/><br/>5. Myspace中国 <br/><a href="http://www.niuc.net/attachment.php?fid=318" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=318" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>“不能为空”，这看上去更像是开发者的表达方式。<br/><br/>6. Uk.match.com<br/><a href="http://www.niuc.net/attachment.php?fid=319" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=319" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a> <br/><br/>7. 豆瓣<br/><a href="http://www.niuc.net/attachment.php?fid=320" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=320" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>直接说明所需要的操作。<br/> <br/><br/><strong>三、密码输入错误，点击登录</strong> <br/><br/>问题分析：出现这种情况可能是因为用户忘记密码，或者密码输入过程中发生了自己未察觉的错误<br/><br/>文案关键点：在明确问题、规则、操作的基础上，尽可能涵盖可能的错误情况；不归罪于用户<br/><br/>1. 谷歌<br/><a href="http://www.niuc.net/attachment.php?fid=321" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=321" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>直接说明问题。一个小问号“？”表示“帮助”，代替了更多话语，也符合用户认知习惯。<br/><br/>2. 百度 <br/><a href="http://www.niuc.net/attachment.php?fid=322" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=322" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>摆明事实，提示操作，直截了当。<br/><br/>3. 淘宝<br/><a href="http://www.niuc.net/attachment.php?fid=323" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=323" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>相对于“密码错误”，“密码不匹配”是更加准确和中性的描述。<br/> <br/>4. Myspace中国<br/><a href="http://www.niuc.net/attachment.php?fid=324" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=324" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>“不太对吧，重试一下？”口语化的提示，用商量的语气。<br/><br/>5. Uk.match.com<br/><a href="http://www.niuc.net/attachment.php?fid=325" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=325" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>中文意思是 “啊哟！我们没有认出你输入的用户名或邮箱地址。请确保拼写正确。记住用户名中只能使用字母、数字和下划线。”和谷歌一样，把问题归因于自身，并且预见了用户可能出现的具体操作问题，给予手把手般的辅助。<br/> <br/>6. 豆瓣<br/><a href="http://www.niuc.net/attachment.php?fid=326" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=326" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>“请再试一次”语气比“请重新输入”柔和了许多。<br/><br/>7. msn中国<br/><a href="http://www.niuc.net/attachment.php?fid=327" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=327" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>很多时候，“重新键入”是解决不了问题的，因为用户根本就是彻底忘记了密码。这个时候“或是注册一个新的帐户”就是有效的提示之一。<br/><br/><strong>总结</strong><br/><br/>有些提示文字，像是老师，手把手教你怎么做；有些呢，像是一位工程师，只提供清晰简短的提示，能不说就不说；有的，像是朋友，帮忙的同时不忘开些小玩笑；还有的，什么都不像，就是冷冰冰的系统提示，可它也是人写出来的：）<br/><br/>你喜欢哪一种？<br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a> , <a href="http://www.niuc.net/tags/%25E4%25BA%25A4%25E4%25BA%2592%25E5%258F%258D%25E9%25A6%2588/" rel="tag">交互反馈</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7906/</link>
<title><![CDATA[关于前端设计中的眼动规律研究]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 06:56:02 +0000</pubDate> 
<guid>http://www.niuc.net/post/7906/</guid> 
<description>
<![CDATA[ 
	设计师常有这样的疑惑：<br/>如何知道用户浏览网页的习惯？<br/>如何设计出符合用户使用习惯的网页？<br/>如何从搜索引擎带来更多的流量？<br/><br/>眼动研究可以帮助我们记录用户浏览网页快速变化的眼睛运动数据，包括：注视点、注视时间、眼跳方向、眼跳距离和瞳孔直径等多种参数，还可以绘制眼动轨迹图，直观而全面地反映眼动的时空特征。<br/><br/><strong>1.眼睛的生理、心理构造</strong><br/><br/>我们的眼睛有两根轴线，一个是光轴， 一个是观察时视线的视轴。简单的说，视网膜与视轴相交处从内而外可以划分为：中央窝、近窝区、边缘视觉。中央窝是最集中的视觉区域，当离开中央窝后分辨率 急剧下降,并且越远越低。近窝区预先阅读中央窝的信息，边缘视觉善于捕捉运动和对比。<br/><a href="http://www.niuc.net/attachment.php?fid=307" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=307" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>我们浏览网页主要分注视和扫视，注视时眼睛相对较旧的“固定”在一个特定的区域，主要信息通过中央窝获取。扫视时眼睛快速、短暂的浏览，主要信息通过近窝区和边缘视觉获取。<br/><a href="http://www.niuc.net/attachment.php?fid=308" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=308" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong>2.眼动研究的历史及意义</strong><br/><br/>眼动实验的原理主要是：在实验当中，主试利用一小束对人体无害的微弱光束，射向被测试人的眼睛，这束从眼球表面反射回来的光就记录了眼球运动的情况。它的意义在于通过对结果进行分析，我们可以了解：用户如何观看一个界面和挖掘影响观看行为背后的设计因素，从而识别界面尚待改进的地方，提供客观的数据来指导设计。<br/><br/>眼动研究在前期主要有观察法、机械记录法、电流记录法等。<br/><br/>观察法是用肉眼直接观察被试的眼动情况，这是一种比较原始的眼动实验法。实验时在被试的面前放一面镜子，主试站在被试后面，由镜子里观察被试的眼动。后来又出现了一种窥视孔法，就是在被试阅读的材料中间穿一个直径为0.76cm的小圆孔。主试可以通过小孔观察被试阅读时的眼动。观察法简便易行，可以在没有仪器的情况下使人了解眼动方面的知识。但它只能对眼动进行比较粗略的研究，其结果不够精确。因此，这一方法很快就被新的方法所取代。<br/><br/>机械记录法是通过把眼睛与记录测验装置用机械传动方法联结起来实现的。主要有头部支点杠杆法、气动法、角膜吸附环状物法等类型，眼动的机械记录法装置复杂，调整起来很麻烦，其实验结果的准确性也较低。<br/><br/>电流记录法原理是：眼球运动可以产生生物电现象，角膜和网膜间存在一个电位差，当眼睛注视前方不动时，可以记录到稳定的基准电位。电位的变化由置于皮肤相应位置的电极导入放大器的电流计显示在示波器上。也可由记录器在记录纸上描记电流变化的波形图。这种方法可以记录到离开注视点70°的眼动，其精确度为1.5°～2.0°。<br/><a href="http://www.niuc.net/attachment.php?fid=309" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=309" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/><strong>3.眼动研究FAQ</strong><br/><br/>问：热点图是否越红=越好，没颜色=没用？<br/><br/>答：不一定。需结合场景，用户的主观解释及其他（点击）分析；颜色代表相对趋势，没颜色不代表绝对看不到。<br/><br/>问：注视时间越长越有吸引力？<br/><br/>答：不一定，注视时间长也可能表示该区域难以理解。<br/><br/>问：我的项目是不是直接拿眼动仪就行了<br/><br/>答：眼动数据不能解决一切问题，且眼动研究对样本数要求高，测试设计要求更严谨。<br/><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a> , <a href="http://www.niuc.net/tags/%25E7%259C%25BC%25E5%258A%25A8%25E7%25A0%2594%25E7%25A9%25B6/" rel="tag">眼动研究</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7905/</link>
<title><![CDATA[网站交互事件全分析]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 22 Oct 2009 06:51:40 +0000</pubDate> 
<guid>http://www.niuc.net/post/7905/</guid> 
<description>
<![CDATA[ 
	<strong>挖坟</strong><br/><br/>交互设计（Interaction Design）产生于二十世纪八十年代，在1984年一次设计会议上，大名鼎鼎的英国交互设计师比尔·莫格里奇首次提出交互设计这个概念，作为一门关注交互体验的新学科而存在并发展到今天，他一开始给它命名为“软面（Soft Face）”，由于这个名字容易让人想起和当时流行的玩具“椰菜娃娃（Cabbage Patch doll）”，他后来把它更名为“Interaction Design”――交互设计。<br/><br/><strong>思考</strong><br/><br/>交互设计是一种如何让产品易用并尽可能让人乐在其中的技术，他包括了解目标用户在产品使用过程中的心理反应，了解用户在同产品交互时彼此的行为，了解大部分用户交互行为的习惯，同时，还包括了解各种有效的交互方式，并对它们进行增强和扩充。交互设计还涉及到多个学科，以及和多领域多背景人员的沟通。<br/><br/>交互设计在产品上的使用也越来越得到各大网站以及网民的重视，交互设计的理论也日益丰满，经典的交互案例也渐渐丰富起来。<br/><br/>今天我们来分析一下互联网上交互设计的一些事件，为大家的研究和应用提一些个人肤浅的看法。<br/><br/>其实交互可以理解为在使用产品过程中用户的感觉以及针对感觉的反馈。从这个层面上来看，生活中交互是无处不在的。交互产生的感觉就是我们平时所熟知的五感，即听觉，视觉，嗅觉，味觉，触觉。当然你一定要认为交互可以给你带来第六感，我也不反对，因为确实有好的交互让你有种神秘莫测的感觉，而且可以让你沿着设计师预想的方向去使用产品。其中应用于互联网的交互设计基本上是没有嗅觉和味觉的，虽然不排除将来可能会相关硬件产品作为这些感觉的输出设备（比如不好看的网站，某输出设备直接散发出臭味，或者某输出设备尝起来很苦），但是我们目前只讨论目前绝大部分输入设备带来的感觉。（注一）<br/><br/><strong>分析</strong><br/><br/>我们在使用互联网产品的时候，听觉，视觉，触觉是经常被触发的。在此我对互联网产品的交互事件进行了分类：听觉交互事件，视觉交互事件，键盘交互事件，鼠标交互事件。后两者虽然都属于触觉交互事件，但基于网民的操作习惯（键盘流，鼠标流），我觉得分开会比较容易讨论这个话题，尽管某些时候他们都混合在一起，难以分开。(注二)<br/><br/><strong>听觉交互事件</strong><br/><br/>听觉交互事件顾名思义就是：耳朵听到的声音给用户感觉，并产生的相关反应的过程。比如WINDOWS的系统提示音，网络游戏中的一些音效，很多论坛的短消息提醒，等等。听觉交互事件的主要交互目的是有四种：提示，警告，反馈，补充。我分别举例说明一下。<br/><br/>提示：比如很多即时通信软件的好友上线提示，系统消息提示。<br/><br/>警告：系统操作错误的警告音，软件登录密码错误，某些游戏中红血警告，时间限定警告，机会限定警告。<br/><br/>反馈：注册成功，升级成功，操作按钮被点击。<br/><br/>补充：很多FLASH站的背景音乐，游戏中的战马嘶鸣、马蹄绝尘、刀剑铿锵，电子杂志翻页音效。<br/><br/>声音交互事件的交互方式很单一，就是默认在交互过程中发出声音。它的优点是提醒用户注意，在输出设备（听筒、音箱等）齐全的情况下，信息传达稳定，用户容易接收，交互效果最好。但它也有缺点，就是受制于输出设备，如果没有音箱或者听筒，交互效果就基本没有。所以听觉交互事件一般不独立用在互联网产品上。<br/><br/>听觉交互事件的注意事项：<br/><br/>1.不独立使用，应该与其他交互事件配合使用，至少要与视觉交互配合。<br/><br/>2.不强制用户接受，有选择项可以让用户关闭，不要期待用户为你去关输出设备。<br/><br/><strong>视觉交互事件</strong><br/><br/>视觉交互事件就是眼睛看到的界面给用户的感觉，并产生的相关反应的过程。视觉交互事件经常和其他交互事件混合在一起使用，但它本身可以独立使用。比如很多线下活动在线上作的网络广告，某些电影的线上海报，某些牛人的个人网站通知，流程图，注册时用户确认已阅读用户协议前不可点击（或倒计时完成后方可点击）的按钮等等。<br/><br/>我再举一个具体的例子，某网站出现一个震撼的广告图，内容为“浙江移动推出充值200送200优惠活动，请到附近营业厅办理。”用户可能不会点击，他会打电话给移动公司询问，或者告知朋友去充值，或者直接就去营业厅办理了。这个人只要有了反应，交互事件就进行得很完美，广告效果就达到了。视觉交互与其他事件交互的结合也比比皆是，我就不一一枚举了。<br/><br/>视觉交互事件是用户最直观最容易获得的体验，因此它需要具备美观，吸引，冲击，共鸣等特点。这一部分与界面视觉设计需要关注的部分重合，但不完全一样。<br/><br/>视觉交互事件的注意事项：<br/><br/>1.表达清晰，有时甚至要牺牲美观来满足信息清晰的传达<br/><br/>2.与目标用户群产生共鸣，从文案、配色、图案等方面来提高吸引力，让用户有深入了解产品的欲望<br/><br/>3.配合其他交互事件使用时，尽可能满足其他交互事件的需求，避免产出好看不中用的华而不实的产品<br/><br/><strong>鼠标交互事件</strong><br/><br/>鼠标交互事件顾名思义就是用户使用产品时，通过鼠标操作产生感觉，并产生相关反应的过程。鼠标交互事件是最常用的也是最重要的交互事件。比如导航条，很多性格测试，不计名投票系统，一些网页版小游戏，某些FLASH广告，部分网站上出现的快捷菜单等等都属于鼠标交互事件。鼠标交互事件包括主键点击，悬浮，双击，选中，副键点击，滚动等，经常体现在超链接,JS写的ON系列事件，FLASH的按钮等场景中。<br/><br/>鼠标交互事件因为操作比较简单，得到很多入门级网民的喜爱，我们在用户体验研究测试中也确实能找到这一类的用户，就是传说中的“鼠标流”，整个交互过程只用鼠标来完成，虽然这不能代表所有网民，但确实代表了一种趋势，用户都喜欢简单的交互方式，只不过我们更关注的是有效，如果用户点来点去，找不到入口（出口），达不到目的，那么这个鼠标交互事件就是失败的，需要改进了。<br/><br/>既然鼠标交互事件有这些需求，我们就应该在设计的时候权衡简单和有效的关系了。必须需要的步骤，我们一步都不能省，我相信用户不会吝惜一次点击的。另外一方面，我们不能因为用户不在乎多一次点击，就让用户不知道先点哪个的地方或者不停地点击。再举个例子，网站的快捷菜单，可以直达很多地方。我们不能把所有的页面都列出来，那样就变成sitemap了，在某个页面上的快捷菜单最好只列出重要的，常用的，或者相关的链接就行了；也不能只列一个“帮助中心”的快捷链接，尽管我相信你的帮助中心作得非常有条理，用户还是需要点了再点，一级接一级的去找到相关的帮助，如果能直接到本页面相关的帮助不是更好？这个权衡非常具有挑战性，希望大家在作交互设计的时候多考虑，多调查，多试验，相信能找到一个比较好的方案。<br/><br/>鼠标交互事件的注意事项：<br/><br/>1.傻瓜式：简单方便，在满足用户使用需求的同时，尽量减少点击次数。<br/><br/>2.提示明显：让用户知道哪里地方可以点击，点击哪里可以最快达成目标。这个需要在界面及文案上对用户给予引导。<br/><br/>3.反馈及时：用户在鼠标交互事件产生之后，能给以及时的反馈，比如鼠标经过变色，点击错误发出警告，跳转页面后能直接到相关的位置，AJAX请求后要反馈出明显的视觉提醒或者页面变化<br/><br/>4.层次分明：用户点击之后，能有整个操作过程的提示，在操作失误后可以返回重新操作，已经点击过的是不是需要记录状态等等。<br/><br/><strong>键盘交互事件</strong><br/><br/>键盘交互事件就是用户使用产品过程中，通过键盘操作产生交互体验的过程。键盘交互在网络产品的交互过程应用得相当普遍，比如撰写日志，添加评论，ENTER提交，小键盘翻页，TAB切换焦点，某些网页游戏的快捷键等等。键盘交互事件通常和鼠标交互混合使用，构成了互联网产品的主要交互行为。用户在进行键盘交互之前，对时间和精力的花费有一定的预期，由于多年互联网产品交互过程对用户习惯的培养，用户在进行键盘交互事件的时候耐心明显多于其他交互事件。所以键盘交互事件要充分利用用户对此事件的耐心，并且要充分尊重用户的习惯。举例说明：文本框里面的提示语在焦点产生的时候要有全选功能或者删除功能；文本框输入完成后要有ENTER提交的功能，而文本域输入完成后则是CTRL+ENTER作为提交，因为ENTER此时会作为换行的用途；有些文本输入有字数限制时需要提示剩余字数；有些文本域输入有时效性，需要有保存草稿功能，或者有时效性的提示；在需要设置快捷键的时候不要和系统默认的一些快捷相冲突，如果冲突了还不如不要。<br/><br/>尊重主流的操作习惯非常重要，在此特别提出。比如我很不喜欢QQ的CTRL+ALT+Z的默认提取消息，因为这是PHOTOSHOP的返回上一步的快捷键，这个设置非常干扰我的工作；我很喜欢GOOGLE文档里的CTRL+Z(俗称后悔键)和CTRL+Y（俗称恢复键），因为它符合大多数互联网产品的操作习惯。虽然有些习惯比较偏向个人，但我相信一定有很多产品自作聪明的设置了一些快捷键，反而干扰了一些常用软件或者系统的默认快捷键，本来是一个好的交互意愿，却取得了相反的交互体验。<br/><br/>键盘交互事件的注意事项：<br/><br/>1.安全性：键盘交互事件可能透露一些用户的个人信息，或者泄露一些隐私，好的互联网产品应该给于用户以保护。<br/><br/>2.稳定性：在利用用户对此交互事件的耐心来收集信息或者获得反馈的同时，要保证用户的耐心要有成果，不能让用户浪费时间和精力，结果前功尽弃，或者功亏一篑。<br/><br/>3.一致性：不要指望用户对键盘交互事件拥有高超的辨别能力而采取不同的操作方式，如果你采用了一种交互方式，尽量在相同或者相似的交互场景中延续使用相同的交互方式，退一步说，不要用不一样的交互方式，再退一步说，千万不要用相反的交互方式。这一点对视觉交互也很重要，但对于能称作界面设计师的人（不包含图片处理员）来说，一般这种一致性是可以保持的。<br/><br/>4.尊重习惯：目前互联网产品中有一些是非常伟大（或者说强大）的产品，不管交互方式是否绝对完美，至少他已经用市场占有率和时间的延续性培养了用户一些既有的习惯，交互设计师不要轻易打破用户的现有习惯，这并不是说不能有创新，而是指在现有习惯上优化和提升交互体验，是对现有交互方式的延展。<br/><br/><strong>总结</strong><br/><br/>以上是我对互联网产品的交互事件所作的分类和分析，尽管现实产品的交互事件都很复杂，但基本是这几种事件的组合，如果我们能在基础的事件上作好交互设计，那把复杂的交互事件作好希望就会很大。<br/><br/>另外业内对一个产品的交互设计作得好不好，没有一个标准，通过以上分析，虽然我们依然无法制定出这一标准，但是我们可以从上面的分析看出一个交互设计是不是作得不好。在我看来，这也是一个进步了。我希望各位同行都来贡献自己的力量，将好的交互设计应用在更多的产品，让用户得到更好的体验。<br/><br/>个人的一些分析，难免有不足，希望大家补充和指正。(本文较长，无图，枯燥，理论，对能读到这里的朋友表示感谢)<br/><br/><strong>补充</strong><br/><br/>注一:<br/><br/>与宗羲讨论时，宗羲认为： “五感”应该是交互的“输入”(input)，也就是通过人类的“五感”作为外界的信息进入大脑，而交互产生的感觉应该摘引《情感化设计》里所描速的三层来描述，即：本能层、行为层、反思层。<br/><br/>宗羲的解释非常正确，但我这里说的五感是具体交互事件产生的感觉，是点到线来分析问题的（纵向），而情感化设计里所提到的三层结构是点到面来分析问题（横向）。个人感觉并不冲突。<br/><br/>注二:<br/><br/>与宗羲继续讨论时，宗羲认为：我个人觉得应该从输入和输出来区分。听觉交互事件，视觉交互事件是交互中的输入(对于人类来说，下同)，即交互设备将信息反馈给人类的过程，键盘交互事件，鼠标交互事件是输出信息，即人类将反馈输出给交互设备。输入+输出就形成了“交互”。<br/><br/>输入和输出的区分方法是可行的，但用来归纳交互事件我觉得有不足的地方，文中有例子表明有些交互事件是直接到达反思层的，可能对交互设备根本没有输出任何信息。<br/><br/>所以虽然有了宗羲的提醒，本文还有留下一个遗憾，就是文章结构不够严谨。点到面的结构经过叠加，可以形成整体，而点到线的结构是不足的，如果线与线之间的关系没有明确表达出来，形成的整体是有缺陷的。<br/>Tags - <a href="http://www.niuc.net/tags/%25E4%25BA%25A4%25E4%25BA%2592%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">交互设计</a> , <a href="http://www.niuc.net/tags/%25E5%2589%258D%25E7%25AB%25AF%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">前端设计</a> , <a href="http://www.niuc.net/tags/html/" rel="tag">html</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7904/</link>
<title><![CDATA[SEO的又一理解]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Seo技术]]></category>
<pubDate>Tue, 20 Oct 2009 04:00:59 +0000</pubDate> 
<guid>http://www.niuc.net/post/7904/</guid> 
<description>
<![CDATA[ 
	<p>最近猫是<abbr title="Search Engine Optimization">SEO</abbr>特别火，真是随处都可以看到，其实我并不喜欢提SEO，套用句话：&ldquo;SEO是钻石，不是每个人都玩得起。&rdquo;我是属于玩不起的那种人，不过做网站也有几个年头了，说一下我的认识：SEO是搜索引擎优化，不过优化不是搜索引擎，而是自己的网站。主要我归成下面二个：</p><ul>&nbsp;&nbsp;&nbsp;&nbsp;<li>网站结构</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>页面内容</li></ul><p>当然，这样归可以有点笼统，简单说一下。蜘蛛捉网页要么深度优先，要么广度优先，衡量链接结构适合两种方式能跑遍网站结构就行，该用<a title="网页搜索帮助-禁止搜索引擎收录的方法" href="http://www.baidu.com/search/robots.html"><font color="#0066cc">robots</font></a>去挡的就去挡，过多的堆积不一定是最好的。</p><p><cite>Google</cite>说：<q><font style="background-color: #f8f8f8">设计网页时该考虑的是用户，而不是搜索引擎。</font></q>，以人为本的设计就不一定能照顾到搜索引擎，当然，搜索引擎也努力在模拟人。可以在网站结构定完后进行一定量地调整链接结构，对于搜索引擎是怎样搜索，我也不知道，我相信很多专业从业SEO的朋友也不一定清楚。不过我倒是知道有好几搜索引擎会去看一下<a title="用Google搜索sitemaps" href="http://www.google.cn/search?complete=1&amp;hl=zh-CN&amp;q=sitemaps&amp;btnG=Google+%E6%90%9C%E7%B4%A2&amp;meta="><font color="#0066cc">sitemaps</font></a>。</p><p>最近看到的SEO多数也是讲到页面内容，说到页面内容，自然就是关键词，关于关键词的选择：有资本就去抢热词，没资本就捡冷词。关于一个页面要多少关键词，这个是高技术含量的东东，我不懂。不过据说有的编辑能拿月薪上W，关键词是基于内容生成滴，一个优秀的编辑在写一篇文章时，就可能有意识或者无意识埋了无数的关键词，虽然他们有时只是想写出更多人阅读的文章，可是他们的用词用字都已经对应了相应的行业。又据说现在的引擎都是全页索引，呵呵，当然精选细选的关键词是理想滴。</p><p>说到页面，自然也要讲到Web Standard，有人说有关系，有人说没。说于说没的朋友，建议去看一下下<a title="Web Content Accessibility Guidelines 2.0" href="http://www.w3.org/TR/WCAG20/"><font color="#0066cc">WCAG</font></a>，一般人我是不告诉他们滴。Web标准不是简单的DIV+CSS或者XHTML+CSS，理想是让各种User agent都可以访问，当然，由于一些终端的局限，相应的M版出来，比如<font color="#0066cc">m.flickr.com</font>等。一个页面可以通用访问，不代表适合访问。</p><p>虽然大家都用XHTML，但用法不同，大家研究语义化的网页也不假的，什么时候用h1，什么时候用h2，也不是说因为h1搜索引擎比较喜欢就选择用的，大家正努力充分发挥(X)HTML各标签的作用，减少大量font之类的东东，虽然不能说很利于搜索引擎，但也帮搜索引擎过滤了一回，html5还&ldquo;开发&rdquo;了几个新标签出来给大家玩。 当然，CSS Layout是优秀的，但也不是说table布局就没用，电视有了，收音机就扔了-_-b， 现在收音机还是播着了大堆有价值的东东。呈现方式不同，有着&ldquo;利于&rdquo;和&ldquo;更利于&rdquo;的区别。</p><p>当然，影响页面还有另一个重要的因素，站外链接，要是你的Blog每天都有无数个垃圾留言的话，这也是SEO的副作用之一，搜索引擎不少用站与站之间的link来评估页面的重要性，比如<abbr title="PageRank">PR</abbr>，不过据说现在不更新鸟。虽然说有nofollow这样高科技的东东，但也有挡不住的激情，就是不知道引擎们会不会喜欢nofollow的东东，不过可以确定的是WP的插件也能实现区别spam，相信那样聪明的搜索引擎也会区分一下下吧。</p><p>好像没说到SEO最最核心的东东。。嗯。我是不会。会也不讲出来^^。要是我能懂得引擎们的算法，我就不在这废话了。给个新手学习的地方: <a href="http://www.google.cn/support/webmasters/bin/answer.py?answer=35769"><font color="#0066cc">网站管理员支持中心 &ndash; 网站管理员指南</font></a>。里面有句话特别喜欢：<q><font style="background-color: #f8f8f8">请不要为了提高搜索引擎排名而弄虚作假</font></q>。不是说SEO不能做，要做就要注意个量（数量/质量）。</p><br/>Tags - <a href="http://www.niuc.net/tags/seo/" rel="tag">seo</a> , <a href="http://www.niuc.net/tags/%25E7%25BD%2591%25E7%25AB%2599%25E4%25BC%2598%25E5%258C%2596/" rel="tag">网站优化</a> , <a href="http://www.niuc.net/tags/seo%25E6%258A%2580%25E6%259C%25AF/" rel="tag">seo技术</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7903/</link>
<title><![CDATA[加快网页中的图片显示]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Html技术]]></category>
<pubDate>Tue, 20 Oct 2009 03:52:12 +0000</pubDate> 
<guid>http://www.niuc.net/post/7903/</guid> 
<description>
<![CDATA[ 
	<p>加速的关键，不是降低重量，而是减少个数。如果重量在200K以内，只要网络不是特别慢，效率都差不多。但是，如果图片个数多一倍，效率将明显低一个档次。</p><p>传统切图讲究精细，图片规格越小越好，重量越小越好，其实规格大小无所谓，计算机统一都按Byte计算。客户端每显示一张图片都会向服务器发送请求，所以，图片越多请求次数越多，造成延迟的可能性也就越大。因为一张图片的传输时间，通常远小于请求等待的时间。</p><p>减少图片的三个技巧(CSS Sprite)：</p><p><strong>1. 图片限制(Image Slicing)</strong></p><p>典型如文本编辑器，小图标特别多，打开时一张张跑出来，给用户的感觉很不好。如果用一张图解决，则不会有这个问题，比如百度空间、163博客、Gmail都是这么做的。</p><p><img alt="" src="attachment.php?fid=299" /></p><p>Image Slicing&rsquo;s Kiss of Death<br /><a target="_blank" href="http://www.alistapart.com/articles/sprites"><font color="#0066cc">http://www.alistapart.com/articles/sprites</font></a></p><p><strong>2. 单图转滚(Single-image Rollovers)</strong></p><p>触发切换图片的需求，传统方案得重新请求新图片，因为网络问题经常造成停留或等待。如果把多种状态合并成一张图，就能完美解决，然后再使用背景图技术模拟动态效果。</p><p><img alt="" src="attachment.php?fid=300" /></p><p>ColorScheme Ratings<br /><a target="_blank" href="http://demo.rexsong.com/200608/colorscheme_ratings/"><font color="#0066cc">http://demo.rexsong.com/200608/colorscheme_ratings/</font></a></p><p><strong>3. 延长背景(Extend Background Image) </strong></p><p>如果图片的某边可以背景平铺无限延长，则不需要每个角、每条边单独搞出来，图片能少一个就少一个。其实，这个理论还可以扩展到四角容器里，好处是能大大简化HTML Structure。</p><p><img alt="" src="attachment.php?fid=301" /> <img alt="" src="attachment.php?fid=302" /></p><p>Extend Background Image<br /><a target="_blank" href="http://demo.rexsong.com/200705/extend_background_image/"><font color="#0066cc">http://demo.rexsong.com/200705/extend_background_image/</font></a></p><h4>综合案例</h4><p>Google Korea（1和2技巧）<br /><a target="_blank" href="http://demo.rexsong.com/200705/google_korea/"><font color="#0066cc">http://demo.rexsong.com/200705/google_korea/</font></a></p><p>&nbsp;</p><p><font color="#0066cc"><img alt="" src="attachment.php?fid=303" /> <img alt="" src="attachment.php?fid=304" /></font></p><p>CSS Menus（2和3技巧）<br /><a target="_blank" href="http://demo.rexsong.com/200705/css_background_menus/"><font color="#b85b5a">http://demo.rexsong.com/200705/css_background_menus/</font></a></p><p><img alt="" src="attachment.php?fid=305" /> <img alt="" src="attachment.php?fid=306" /></p><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E7%25BD%2591%25E9%25A1%25B5%25E4%25BC%2598%25E5%258C%2596/" rel="tag">网页优化</a> , <a href="http://www.niuc.net/tags/%25E7%25BD%2591%25E9%25A1%25B5%25E5%258A%25A0%25E9%2580%259F/" rel="tag">网页加速</a> , <a href="http://www.niuc.net/tags/%25E5%259B%25BE%25E7%2589%2587%25E5%258A%25A0%25E9%2580%259F/" rel="tag">图片加速</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7902/</link>
<title><![CDATA[如何快速的呈现我们的网页]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Html技术]]></category>
<pubDate>Tue, 20 Oct 2009 03:48:27 +0000</pubDate> 
<guid>http://www.niuc.net/post/7902/</guid> 
<description>
<![CDATA[ 
	<p>特别说一下了，这些方案并非适合所有的网站，很多部分有的网站还是不要做反而会更好。</p><h3>一.我们需达解决的麻烦</h3><ul class="upper-alpha">&nbsp;&nbsp;&nbsp;&nbsp;<li>减少HTTP请求数. 减少HTTP请求数有什么好处&nbsp;&nbsp;&nbsp;&nbsp;<ul>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<li>降低服务器跟客户端的建立和消除HTTP请求和响应Header的开销</li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<li>减少服务器为HTTP连接的进程和线程的开销,如果可能,还会包括GZIP压缩的CPU开销.</li>&nbsp;&nbsp;&nbsp;&nbsp;</ul>&nbsp;&nbsp;&nbsp;&nbsp;</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>减小被请求文件大小, 减少请求数据占用的网络带宽.</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>让用户更快的看到想要的结果.</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>提高客户端渲染速度.</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>让浏览器同时能请求更多的数据.</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>提高服务器相应速度.</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>通过版本化控制客户端Cache.</li></ul><h3>二.如何解决我们的麻烦</h3><h4>A.如何减少HTTP请求数</h4><ol>&nbsp;&nbsp;&nbsp;&nbsp;<li>合并JS文件跟CSS文件。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>合并框架图片以及相对变动较少的图片成一张，通过CSS背景切割来完成渲染，比如：<font color="#0066cc"><a href="http://www.niuc.net/post/7903/">加速图片显示</a></font>。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>合理使用本地Cache来缓存JS/CSS/IMAGE。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>合理使用UserData缓存JS文件，对于FF用户可以单独请求服务器,这样能解决80%用户的问题。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>把JS跟CSS合并成一个文件。</li></ol><h4>B.减小被请求文件大小,减少请求数据占用的网络带宽</h4><ol>&nbsp;&nbsp;&nbsp;&nbsp;<li>压缩JS体积：删除JS中空白换行,注释,混淆把长变量换成短变量；</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>压缩CSS体积：删除CSS注释、写法尽量用简写；</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>使用(X)HTML+CSS方式搭建网站结构,提高CSS重用性,来减少(X)HTML文件大小；</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>使用服务器端GZIP压缩JS/ CSS文件,缩小传输文件大小。附注:Apache1跟Apache2的GZIP的效率跟方式不一样的，根据需要自行选择。</li></ol><p>嗷嗷补充说明：压缩、合并JS和CSS都由程序处理。而不是自己手动去缩删，不然不利于后期维护。</p><h4>C.让用户更快的看到想要的结果</h4><p>用户对于一个站点的白页的忍受时间根据统计是8-12秒。白页的产生可能由于各种原因引起,我们能做的就是怎么让用户能变的稍微能等待更久。</p><ul>&nbsp;&nbsp;&nbsp;&nbsp;<li>方案1.多做一个引导页,让用户体会其中的变化<br />&nbsp;&nbsp;&nbsp;&nbsp;案例:mail.aol.com中的loading引导页</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>方案2.优先载入页面结构以及结构图片,后一步载入当前页面数据,再后一步载入Iframe,Flash等数据.让用户尽早的看到被打开页面的希望.</li></ul><h4>D.提高客户端渲染速度</h4><p>这个问题就比较泛泛了,影响客户端的渲染速度有多方面的,主要目的都是提高程序方面的效率.</p><ol>&nbsp;&nbsp;&nbsp;&nbsp;<li>对于大索引的结构,尽可能的少用索引访问,能用访问兄弟节点的方式尽可能用访问兄弟节点的方式.</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>字符串拼接尽可能用数组方式</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>大规模添加节点数据,请不要使用appendChild方式,尽量使用类似innerHTML的insertAdjacentHTML方式,FF下需修正<sup><a href="http://www.niuc.net/post/7902/#f1"><font color="#0066cc">1</font></a></sup></li></ol><h4>E.让浏览器同时能请求更多的数据.</h4><p>浏览器默认只是支持单域名同时有两个HTTP请求,使用多域名将能把请求数提高,在网络条件优良的情况下,能更快的下载数据,呈现结果.</p><h4>F.提高服务器相应速度</h4><p>对于需快速响应的文件,把其放入快速响应的服务器,应该是不错的方案,优化方案请系统储备组提供.</p><h4>G.通过版本化控制客户端Cache.</h4><p>通常js/css这类文件改动比较频繁,但是为了加载速度变快,我们有可能需要设定这类文件的过期时间为几天后,这样我们碰到的问题就是,如何及时更新这些在cache的文件?<br />通过一个简单的配置,通过修改JS的版本来及时告诉浏览器,这些文件必须重新请求了,不要继续使用浏览器cache中的数据. 方案有好几个:</p><ol>&nbsp;&nbsp;&nbsp;&nbsp;<li>手动改这些js的文件名</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>手动改这些js的路径</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>通过URL Rewrite方式来改重定位js路径</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>通过一个在高响应服务器上的一个js配置告知页面,这个页面该链接哪些JS文件</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>大版本不变,小版本不断追加,等一定时间后,统一更新,高效利用cache</li></ol><hr /><h4>标注</h4><ol>&nbsp;&nbsp;&nbsp;&nbsp;<li><a title="f1" name="f1"></a>Firefox修正方式<br />[codes=JS]function addHTML(oParentNode, sHTML) {<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(window.addEventListener) {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// for MOZ <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var oRange = oParentNode.ownerDocument.createRange();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oRange.setStartBefore(oParentNode);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var oFrag = oRange.createContextualFragment(sHTML);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oParentNode.appendChild(oFrag);<br/>&nbsp;&nbsp;&nbsp;&nbsp;} else {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// for IE5+<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oParentNode.insertAdjacentHTML(&quot;BeforeEnd&quot;, sHTML);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}[/codes]</li></ol><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E9%25A1%25B5%25E9%259D%25A2%25E5%258A%25A0%25E9%2580%259F/" rel="tag">页面加速</a> , <a href="http://www.niuc.net/tags/%25E9%25A1%25B5%25E9%259D%25A2%25E4%25BC%2598%25E5%258C%2596/" rel="tag">页面优化</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7901/</link>
<title><![CDATA[减少网页的内存与CPU占用]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Html技术]]></category>
<pubDate>Tue, 20 Oct 2009 03:41:15 +0000</pubDate> 
<guid>http://www.niuc.net/post/7901/</guid> 
<description>
<![CDATA[ 
	<p>有的网页看起来并不大但打开会很卡，有的网页虽然很长但使用流畅，占用用户电脑的内存与CPU就影响这些。</p><p>浏览器问题，有各自的浏览器处理内存问题会影响到，但几乎没办法控制得了，Windows上的：</p><ul>&nbsp;&nbsp;&nbsp;&nbsp;<li>IE系列，刷新回收的量不大，但最小化会释放内存，。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>Firefox2据说也会在最小化回收，可我从没见过最垃圾，用多少是多少，基本不回收。据说prototype的ajax还会引起内存一直增加。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>Opera最好。一直控制得很好。不存在什么问题。。</li></ul><p>Linux的内存分配机制与Win的不一样，有多少用多少，如果浏览器占光时说不定会干掉系统。</p><p>页面问题，浏览器渲染页面会消耗内存和CPU，能减少一点就减少点。</p><h4>结构上</h4><ul>&nbsp;&nbsp;&nbsp;&nbsp;<li>使用DocType，告诉浏览器你在用什么，html4也有DTD。也许Transitional更适合你</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>如果使用的是XHTML并能保持良好结构的话，记得输出相应的MIME跟XML头<sup><a href="http://www.niuc.net/post/7901/#f1"><font color="#0066cc">1</font></a></sup>，可以减少浏览器的代码检查，</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>保持结构的完整，不要让浏览器帮你补全代码。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>控制页面的文件大小，可以通过程序把为了看代码比较舒服的缩进去掉。2~3K也是大小。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>iframe会产生新的页面，其实有很多方式可以代替iframe</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>引入的JS与CSS可以适当合并，同样背景图片也可以合并，甚至有人连Flash都合并</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>给已知宽高的内容图片/Object加上宽度的属性可以减少页面的局部重渲染</li></ul><h4>表现上</h4><ul>&nbsp;&nbsp;&nbsp;&nbsp;<li>质量99跟70的jpg在大多数情况下只有文件有大小不一样。gif的也一样，特别是小图标，256色跟128色的差别是文件大小．</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>flash动得太快吃CPU很大，控制每秒的帧数及动画的效果可以减少一些，如果把品质用中低显示会省很多资源，但这样却牺牲了效果。。quality属性 有时选择Autolow<sup><a href="http://www.niuc.net/post/7901/#f2"><font color="#0066cc">2</font></a></sup> 或者Autohigh会更适合，没必要一直low 或者best，</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>flash使用矢量图会节省文件大小，但计算复杂的图形跟动画时花的是CPU。复杂的太多滤镜，则会占用大量内存，模糊滤镜有减少些<sup><a href="http://www.niuc.net/post/7901/#f3"><font color="#0066cc">3</font></a></sup>。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>IE的滤镜也是比较占用内存，同时也有兼容性问题。全屏的半透明很吃资源的。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>2*2的图片跟8*8的图片大小差不多，但是平铺背景2*2却占用大很多。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>gif动画同样有帧的概念，别把gif当成flash来玩就行。</li></ul><h4>行为上</h4><ul>&nbsp;&nbsp;&nbsp;&nbsp;<li>别为了使用一个$()引入整个prototype或jQuery，它们有更多的作用。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>AJAX很帅。但是用xml会用上XML解析器，有人推荐用JSON，可是这样要eval数据，其实可以直接import已经是对象的script来用。只是要多传个对象名，或者把对象名写死，或者像flickr那样<code><font face="Consolas" style="background-color: #f8f8f8">jsonFlickrApi({&quot;xxx&quot;:&quot;xxx&quot;})</font></code>，直接当函数用，挖哈哈。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>实现某些效果时能用<code><font face="Consolas" style="background-color: #f8f8f8">visibility:hidden</font></code>解决时就别用<code><font face="Consolas" style="background-color: #f8f8f8">display:none</font></code>来玩。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li>在这里强调js变量要注全局跟局部等等的意义并不大，JS复杂的地方也不是一两句能说得清的，关注大家关注月影的正在出版的新书吧。^^</li></ul><p>其实这里有的内容有不少跟<a href="http://www.aoao.org.cn/blog/2007/06/how-to-show-our-pages-quickly/"><font color="#0066cc">如何快速的呈现我们的网页</font></a>相近，不过那篇是以处理服务端为主，但在很多时候，节省服务端资源消耗的同时也会节省客户端的资源消耗。</p><p>再其实，这篇已经蹲在草稿箱里好久了，一直没有时间去整理。现在给的也不是完整的，因为没有完整，慢慢补充吧。</p><hr /><ol>&nbsp;&nbsp;&nbsp;&nbsp;<li><a class=" FCK__AnchorC FCK__AnchorC" name="f1">产生问题</a>：虽然会引起浏览器的模式问题，但问题是可以解决滴。参考<a href="http://keystonewebsites.com/articles/mime_type.php"><font color="#0066cc">Serving up XHTML with the correct MIME type</font></a>，派送XML头浏览器不会容错显示，出现错误结构会导致整个页面无法显法。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li><a class=" FCK__AnchorC FCK__AnchorC" name="f2">Autolow</a>: 优先考虑速度，但是也会尽可能改善外观。 回放开始时，消除锯齿功能处于关闭状态。 如果 Flash Player 检测到处理器可以处理消除锯齿功能，就会打开该功能。 <br />&nbsp;&nbsp;&nbsp;&nbsp;Autohigh:开始时回放速度和外观两者并重，必要时会牺牲外观来保证回放速度。 回放开始时，消除锯齿功能处于打开状态。如果实际帧频降到指定帧频之下，就会关闭消除锯齿功能以提高回放速度。使用此设置可模拟&ldquo;消除锯齿&rdquo;命令（&ldquo;视图&rdquo;&gt;&ldquo;预览模式&rdquo;&gt;&ldquo;消除锯齿&rdquo;）。</li>&nbsp;&nbsp;&nbsp;&nbsp;<li><a class=" FCK__AnchorC FCK__AnchorC" name="f3">模糊滤镜</a>:使用模糊滤镜时，如果用于 blurX 和 blurY 的值是 2 的整数次幂（例如 2、4、8、16 和 32），则可以加快计算速度，并且可以使性能提高 20% 到 30%（flash的帮助是介样说滴）。</li></ol><script type="text/javascript">AKPC_IDS += "84,";</script><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E7%25BD%2591%25E9%25A1%25B5%25E4%25BC%2598%25E5%258C%2596/" rel="tag">网页优化</a> , <a href="http://www.niuc.net/tags/%25E7%25BD%2591%25E9%25A1%25B5%25E5%258A%25A0%25E9%2580%259F/" rel="tag">网页加速</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7900/</link>
<title><![CDATA[交互到底是做什么的？]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Html技术]]></category>
<pubDate>Tue, 20 Oct 2009 03:24:34 +0000</pubDate> 
<guid>http://www.niuc.net/post/7900/</guid> 
<description>
<![CDATA[ 
	听说个事情，产品人员A拿着类似如下的这张图跟交互设计B说：这个页面的原型我替你做好了，你让C开始视觉设计吧... ...<br/><br/><a href="http://www.niuc.net/attachment.php?fid=298" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=298" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>听完挺郁闷的，不仅是为交互的工作价值被无视而唏嘘，也是在为公司的招人不慎而忧虑，怎么就让这些不懂事的混进来了呢，影响团队质量啊。<br/><br/>不能忍了，今天就以这个图中最简单的文本框为例，简要的说一说交互到底是干什么吧：<br/><br/>一个交互在听到或看到这个方案时一般会考虑这么几个基本问题：<br/><br/><strong>1. 确实需要这个东西么？</strong><br/>用户确实需要在这里输入、编辑文本或数值么？如果是，OK，那确实需要。<br/><br/><strong>2.这个东西是什么，用什么最合适？</strong><br/>必须是文本框么？如果是，那需不需要带微调组件？输入数据受哪些限制么？把所有要输入的有效值都罗列出来是否可行，如果是，那单选列表框、下拉列表、可编辑的下拉列表是否更加方便?甚至是滑块呢？如果用户需要对所有有效值进行尝试性输入并希望立即得到反馈的话，滑块无疑是最合适的。（用ps的回想一下你“crtl L”、 “crtl U”后的使用情景。）<br/><br/><strong>3.这个东西该长什么样子？</strong><br/>需要输入的数据是格式化的还是非格式化的，系统能把非格式化的输入自动识别成格式化数据么？如果不能而需要采用连续文本框（就类似于输入CD-key的那种组框）的话，自动离开（切换焦点）功能是否需要，规则怎么定？；如果可以做成单一文本框，那长度应该定成多少，才能既避免内容遮挡引发的不必要滚动，又能节省屏幕空间还不给用户造成输入前的心理压力？<br/><br/><strong>4.交互方式是怎样的？（文本框还有交互方式？是的，有，而且还不少）</strong><br/>是否需要辅助输入和自动完成功能？数据对齐方式是什么？内容非空的情况下，获得焦点时是全选显示还是插入光标？（这取决于用户需求，选中文本框是为了替换删除里面的内容，还是插入补充继续完善？前者全选，后者光标。这个问题很影响用户体验，但又经常被忽略掉）<br/>另外，文本框内容的校验规则以及提示/反馈的样式，也需要非常全面而深入的考虑，因为之前有写过一篇文章来浅析这个问题，这里就不废话了。<br/><br/>... ... <br/><br/>以上这些，都是交互设计应该考虑的事情，而且是最基本的、最常见的、未作针对性深入挖掘的。你还觉得交互的工作就是拖个控件出来摆摆位置然后生成个demo么？<br/><br/>现在公司们对员工的要求越来越高高，既要懂那个又要懂这个，UE的要有市场嗅觉，产品的要能设计交互demo... ...我觉得这种风气误导性很强，还是术业有专攻吧，把自己的本分做好最重要。最怕的就是那些自己的本分都做不好，又不了解别人的本分是什么的主儿。<br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E4%25BA%25A4%25E4%25BA%2592/" rel="tag">交互</a> , <a href="http://www.niuc.net/tags/%25E6%258E%25A7%25E4%25BB%25B6/" rel="tag">控件</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7899/</link>
<title><![CDATA[纸上原型设计方法说明及使用规范]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Tue, 20 Oct 2009 03:17:36 +0000</pubDate> 
<guid>http://www.niuc.net/post/7899/</guid> 
<description>
<![CDATA[ 
	<p>做纸上原型这个东西有两个目的：</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">1. 把业内一些零碎和模糊的东西进行分析、整理并加以亲身实践，制定成使用说明或者标准化的设计工具。现在国内的交互从业者对一些概念和工具的理解基本上只停留在老外创造的美好词汇和自己的臆想之中，融入到工作实践时总有这样那样的不靠谱，这并不是东西本身不实用，而是师夷长技的时候并没有结合自身情况。</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">&nbsp;</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">2. 抛块砖，引堆玉。希望童鞋们把UED的相关方法、工具和经验成果都规范总结起来，提高自己工作效率和作品质量的同时，也为整个UED行业的发展壮大贡献力量。在这条方兴未艾的行业道路上，我们需要交换思想，互相启发，彼此搀扶，共同进步。</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">&nbsp;</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">以下提供一份阿里巴巴的纸上原型设计方法说明及使用规范（PDF文档），大家有兴趣可以看看！</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">&nbsp;</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">这个文件只能在登入之后下载。请先 <a href="/login.php?job=register">注册</a> 或 <a href="/login.php">登入</a></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt">&nbsp;</p><p>&nbsp;</p><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E5%25BF%25AB%25E9%2580%259F%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">快速设计</a> , <a href="http://www.niuc.net/tags/%25E7%25BA%25B8%25E4%25B8%258A%25E5%258E%259F%25E5%259E%258B/" rel="tag">纸上原型</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7898/</link>
<title><![CDATA[用户体验设计指南—全局设定—页面布局]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Html技术]]></category>
<pubDate>Tue, 20 Oct 2009 02:17:46 +0000</pubDate> 
<guid>http://www.niuc.net/post/7898/</guid> 
<description>
<![CDATA[ 
	<p><strong><span style="font-size: 16px">什么是布局？</span></strong></p><p>&ldquo;布局&rdquo;是指页面内容的尺寸、间距及位置。有效的布局对于帮助用户快速找到他们想要的内容至关重要，并可以在结构外观上令用户感到舒服。</p><p><span style="font-size: 16px"><strong>如何设计有效的布局？</strong></span></p><p><strong><span style="color: #ff0000">1. 具有清晰的视觉层次。</span></strong><span>布局应当让页面各元素之间的关系和重要性一目了然。你可以通过适当使用下列属性来实现视觉层次：</span></p><ul><li>焦点：指用户首先关注的区域。形式上被赋予焦点属性的UI元素一定要表达重要的内容。</li><li>视觉流：指用户关注区域的顺序。可以根据任务逻辑和用户的浏览习惯来设计恰当的视觉流。好的视觉流应该清晰、合理、顺畅、自然。</li></ul><p style="text-align: center"><img alt="" src="attachment.php?fid=281" /> <img alt="" src="attachment.php?fid=282" /></p><ul><li>关联：在逻辑上相关的UI元素应具有清晰的视觉关系。</li></ul><p style="text-align: center"><strong>错误：</strong><span style="color: #333333">逻辑上相关的UI元素在空间上被分隔，且没有明显的视觉关联。</span><br /><img alt="" src="attachment.php?fid=283" /><br /></p><ul><li>对齐：使页面工整，信息呈现有序，便于用户扫视。</li></ul><p style="text-align: center"><strong>错误：</strong><span style="color: #333333">没有对齐影响了页面效果且不便于用户扫视。不要因为功能需要和对极限情况的顾虑而轻易牺牲掉页面的视觉展现。</span><br /><img alt="" src="attachment.php?fid=284" /><br /></p><ul><li>强调：可以根据UI元素间的相对重要程度进行强调。</li></ul><p><br /><strong><span style="color: #ff0000">2.针对用户的阅读模式来设计布局。</span></strong></p><ul><li>大部分人的阅读习惯是从左向右，至上而下。</li><li>阅读分为沉浸式阅读（immersive reading）和扫视（scanning），前者的目的在于理解，后者在于定位。</li></ul><p style="text-align: center"><img alt="" src="attachment.php?fid=285" /> <img alt="" src="attachment.php?fid=286" /></p><ul><li>浏览网站时，用户不会沉浸在UI本身，而是沉浸在他们的目标任务中，因此扫视是最常使用的阅读模式。用户只在确信必要时才仔细阅读大量文本。</li><li>针对扫视的布局设计可以适当强调主要的UI元素，弱化次要的。包括：</li><span style="margin-left: 40px">1) 将主UI元素放在扫视路径上。</span><br/><span style="margin-left: 40px">2) 避免将重要信息放在左下角或者页面底端或者需要滚动很多的控件上。</span><br/><span style="margin-left: 40px">3) 考虑使用渐进展开方式来隐藏次要的UI元素。</span><br/><span style="margin-left: 40px">4) 将任务相关的重要信息要直接表现在控件上。用户更倾向于关注交互控件上的标签，而不是辅助型的静态文本。</span><br/></ul><p style="text-align: center"><strong>错误：</strong><span style="color: #333333">用户必须阅读辅助型文本后才能明确&ldquo;确定&rdquo;按钮的作用。</span><br /><img alt="" src="attachment.php?fid=287" /></p><p style="text-align: center"><strong>正确：</strong><span style="color: #333333">直接将按钮的作用描述作为控件标签，便于用户理解。</span><br /><img alt="" src="attachment.php?fid=288" /><br /></p><span style="margin-left: 40px">5) 不要展示大段文本，去除不必要的文本。多文本时格式化展示。</span><br/><span style="margin-left: 40px">注：常规模式也存在例外。眼动议实验指出，真实用户的行为很没有规律。此模式的目的在于帮助你做出更好的决定，而不是精准的描述用户行为。</span><br/><p><strong><span style="color: #ff0000">3.合理利用页面空间。</span></strong></p><ul><li>保持页面的视觉平衡。避免拥挤和对空间的浪费。</li><li>确保关键数据没有被截断，除非数据特别长。</li></ul><p style="text-align: center"><strong>错误：</strong><span style="color: #333333">有效空间没有被充分利用，从而导致多条关键数据被截断。</span><br /><img alt="" src="attachment.php?fid=289" /><br /></p><ul><li>控件的尺寸和间距恰当，没有不必要的滚动。一个任务尽量在一屏内完成。</li><li>实际情况中，我们用户的页面空间要小于屏幕分辨率，它会因各种因素而压缩，如：非全屏操作（弹出窗口和对比浏览），浏览器本身及各种辅助栏对屏幕的占用等，设计中要考虑这些情况。</li></ul><p style="text-align: center"><img alt="" src="attachment.php?fid=290" /> <img alt="" src="attachment.php?fid=294" /></p><p><strong><span style="color: #ff0000">4.不要让布局本身成为突出的UI元素，保持视觉简洁（visual simplicity）。</span></strong></p><ul><li>减少内容和展现上的嵌套层级。</li><li>减少控件不同尺寸的数量，例如，在界面上只使用一两种按钮宽度。</li><li>采用轻量级的分组和分割方式，可以用布局本身和分隔符代替分组框。</li><li>使用尽量少的对齐线。</li></ul><p> <strong><span style="color: #ff0000">5.选择与页面类型相匹配的版式。</span></strong>在设计之初，应充分考虑页面承载的内容、功能和属性，继而选择适合该页面的版式。不合适的版式会造成用户的阅读困扰，降低任务的完成效率。</p><p><strong><span style="font-size: 16px">标准和规范：</span></strong></p><p><strong><span style="color: #ff0000">1.栅格化：</span></strong></p><ul><li>我们所说的栅格化是指在网页设计工作中对栅格系统的建立和应用。网页栅格系统来源于平面栅格系统，它以规则的网格阵列来指导和规范网页中的版面布局以及信息分布。</li><li>栅格化可以使信息呈现工整简洁、美观易读，降低页面开发和运维成本。它结构变化相对灵活，扩展性强。</li></ul><p><strong><span style="color: #ff0000">2.以8px为横向栅格单位：</span></strong></p><ul><li>以8px为横向栅格单位，页面所有元素宽度都可以是2的倍数，包括图片和版块宽度，这样可以在一定程度上加快页面（特别是对于J-PEG图片）的渲染速度（基于计算机内部二进制的运算机制）。其在扩展和兼容性上也有一定优势。</li><li>在阿里巴巴中文站中，布局间距的最小单位为8px，布局区块采用32px（8px*4）和24（8px*3）两种粒度单位，分别组成以下两种可实现的栅格系统：</li></ul><p style="text-align: center"><strong>32px</strong>：适用于市场、社区等相关页面<br /><img alt="" src="attachment.php?fid=295" /></p><p style="text-align: center"><strong>24px</strong>：适用于旺铺相关页面<br /><img alt="" src="attachment.php?fid=296" /></p><p><br /><strong><span style="color: #ff0000">3.页面定宽：</span></strong></p><ul><li>自适应可以根据浏览器显示情况自动调整页面宽度，但是因为用户水平方向的聚焦范围有限，所以当页面过宽时，用户的浏览和操作成本会增加；而当页面过窄时（如用户同时开启两个浏览器对比查看商品搜索结果），自适应则会导致布局变形和内容错乱。给页面规定宽度可以避免这些问题。</li><li>在综合考虑当下主流分辨率情况、浏览器外观对显示空间的占用、人机工程学中对水平视角和聚焦范围的规定以及8px单位等多种因素后，我们认为960px是一个相对更加合理的页面宽度。在阿里巴巴中文网站中，推荐使用定宽960px的页面，去除左右各4px的边距，中间的可视宽度为952px。</li></ul><br/>Tags - <a href="http://www.niuc.net/tags/html/" rel="tag">html</a> , <a href="http://www.niuc.net/tags/%25E7%2594%25A8%25E6%2588%25B7%25E4%25BD%2593%25E9%25AA%258C/" rel="tag">用户体验</a> , <a href="http://www.niuc.net/tags/%25E8%25AE%25BE%25E8%25AE%25A1%25E6%258C%2587%25E5%258D%2597/" rel="tag">设计指南</a> , <a href="http://www.niuc.net/tags/%25E9%25A1%25B5%25E9%259D%25A2%25E5%25B8%2583%25E5%25B1%2580/" rel="tag">页面布局</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/alias/sothink-swf-decompiler-v52-521-cdkey/</link>
<title><![CDATA[Sothink SWF Decompiler 5.2 (521)注册码(cd-key)]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Mon, 19 Oct 2009 02:30:39 +0000</pubDate> 
<guid>http://www.niuc.net/alias/sothink-swf-decompiler-v52-521-cdkey/</guid> 
<description>
<![CDATA[ 
	软件名称：<strong>Sothink SWF Decompiler</strong><br/>软件版本：5.2(521)<br/>适用平台：2000/2003/XP/Vista/Windows 7<br/>文件下载：<a href="http://www2.sothink.com/download/swfdec.zip" target="_blank">http://www2.sothink.com/download/swfdec.zip</a><br/><br/><strong>功能简介：</strong><br/><br/>　　Sothink SWF Decompiler 是一个用于将 SWF 转换为 FLA 以及将元素从 SWF 中解压为多种格式的专业工具；支付同时导出多个文件。兼容所有版本的 Flash，包括 Flash 6、Flash 7、Flash 8、Flash CS3 (9.0) 和 Flash CS4 (10.0)。同时支持 ActionScript 2.0 和 3.0。转换之后，您可以得到包括连接、组件、*.as 等等的完整的 FLA 文件。<br/><br/>　　使用 SWF Decompiler，您可以将 Flash 影片的任何元素解压为 SWF、FLA 或它们的共同格式，如形状、变形、声音、视频、帧、字体、文本、按钮、动画和脚本。例如您可以解压脚本为 AS 或 BIN 文件，获取声音为 MP3 或 WAV，图像为 JPEG、BMP 或 PNG，视频为 FLV，形状为 GLS 等等。同时支付标准 SWF 和 EXE (Flash 项目)。<br/><br/>　　Sothink SWF Decompiler 提供友好的用户界面(类似 Office 2007)。内建的播放器让您可以在导出前预览影片和每一个元素。预览窗口里的缩略图视图和导航栏让您可以轻易拾取元素。并且界面布局可以自定义以适应您的需要。<br/><br/><strong>主要功能：</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* 反编译 SWF 为 FLA。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 反编译 SWF 为 FLEX 方案，并获得 MXML 和其它方案文件<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 反编译 Adobe Flash 创建的标准 EXE 为 FLA 格式。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持 Flash 6、Flash MX 2004 (V7)、Flash 8、Flash CS3 (V9) 和 Flash CS4 (V10)。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 兼容 ActionScript 2 和 ActionScript 3。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 导出 SWF 为 FLA 或 FLEX 方案，并能用批处理模式解压资源。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持导出资源为 SWF 或 FLA 格式。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 以多种格式解压元素，包括形状、声音、图像、动画、字体、文本、脚本等等。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 导出 ActionScript 文件为 AS、、BIN 或 HTML 格式。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 从 Flash 影片导出视频文件为 FLV 格式。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 多语言界面，包括英语、德语、简体中文和繁体中文。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 使用 SWF Catcher 从 IE 或 FireFox 捕获 Flash 影片，并将 SWF 影片保存到本地磁盘上。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 以多种格式解压 SWF 影片资源。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持 Flash 组件。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 提供友好的用户界面(类似 Office 2007)。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 反编译 Flash 前可以在预览窗口导航和浏览资源。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 从类似 Windows 般友好的资源管理器激活 Flash SWF。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 提供播放器以播放硬盘或局域网的 SWF。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 可以在预览窗口中对正在播放的 Flash 影片截图保存到文件或剪贴板。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 提供播放控制栏来自由播放、停止、前进、后退、放大、缩小和定位 Flash 影片。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 显示 Flash 影片元素的详细属性。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 优化资源面板里的脚本显示。当反编译 AS3.0 时，支持根据它在包里的路径以树状显示 AS 类结构。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持扫描 IE 的缓冲并列出您看过的所有 Flash 文件。<br/><br/><strong>更新：</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持将用 FLEX 创建的 SWF 文件导出为 FLEX 方案文件。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持多语言界面，包括英语、德语、简体中文和繁体中文。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 支持 Windows XP、Vista、Server 2008 64 位 OS。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* 优化多重导出面板。<br/><br/><strong>修复 Bugs：</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* 在 Flash 播放器里打开 SWF 文件弹出错误。<br/>&nbsp;&nbsp;&nbsp;&nbsp;* Ribbon 工具栏错误。<br/><br/><strong>简体中文补丁：</strong><br/>&nbsp;&nbsp;&nbsp;&nbsp;* <a href="attachment.php?fid=280">点击这里下载文件</a><br/><br/><strong>注册码（cd-key）：</strong>以下4组注册码（cd-key）任选一组~~~<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* Name: Ali1100<br/>&nbsp;&nbsp;&nbsp;&nbsp;* key: 031HE5-73WZMZ-M5T1ZV-UBRXF7-90HHPE-CEU2DY-JF5K7M-D5C4HG-X16FAB-BMNMZK-3BP8T7-TMZNY7<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* Name: Ali1100<br/>&nbsp;&nbsp;&nbsp;&nbsp;* key : 031HE5-73WZMZ-M5T1ZV-UBRXF7-90HKEX-GKRZQX-3P96B2-Q2WYUN-V6T10V-MKPNPF-DJG1G7-Q16E4J<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* Name: Ali1100<br/>&nbsp;&nbsp;&nbsp;&nbsp;* key: 031HE5-73WZMZ-M5T1ZV-UBRXF7-90HGT1-N8DF7V-TET84C-BGKN60-8FW53J-C2E0EM-6XB13Y-26PVYD<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* Name: Ali1100<br/>&nbsp;&nbsp;&nbsp;&nbsp;* key: 031HE5-73WZMZ-M5T1ZV-UBRXF7-90HK19-A5VGUY-7Y5VVW-Z8G9U1-8TF0UY-E64TXW-35NVW3-JG3452<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;* Name: Ali1100<br/>&nbsp;&nbsp;&nbsp;&nbsp;* key: 031HE5-73WZMZ-M5T1ZV-UBRXF7-90HMMK-M690Z3-7T6J9D-F7AAWV-W760D6-JQH23U-V5EPQ8-EJZT6F<br/>Tags - <a href="http://www.niuc.net/tags/flash/" rel="tag">flash</a> , <a href="http://www.niuc.net/tags/flash%25E5%258F%258D%25E7%25BC%2596%25E8%25AF%2591/" rel="tag">flash反编译</a> , <a href="http://www.niuc.net/tags/flash%25E5%258F%258D%25E7%25BC%2596%25E8%25AF%2591%25E5%25B7%25A5%25E5%2585%25B7/" rel="tag">flash反编译工具</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7896/</link>
<title><![CDATA[牛人自传]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Fri, 09 Oct 2009 01:49:52 +0000</pubDate> 
<guid>http://www.niuc.net/post/7896/</guid> 
<description>
<![CDATA[ 
	牛人自传（非我也）<br/><br/>开始了：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 跟自己5年的媳妇让劲舞上的小白脸给拐跑了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为朋友打架，拘留15天，出来之后我一个人赔医药费。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&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;&nbsp;&nbsp; 房没了，租个房天天晚上闹鬼，墙太薄，天天晚上听隔壁的叫床，而且声音还是一男的。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 买了条吉娃娃养了2月结果发现是哈士奇。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网上拍一妞，一见面才知道是离婚的，她儿子比我小一岁，现在天天追杀我，说是为了我离的，我去，你离婚了2年才认识我，你丫还非说是女人的预感。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 夜里喝醉去1912，醒了之后看见和一男的在宾馆里，到现在都不知道让没让他给……<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&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;&nbsp;&nbsp; 饿了就啃我衣服，狗粮从来不吃，晚上趁我睡着了，自己偷冰箱里的大蒜吃。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我说你丫到底是不是狗啊，拉大街上溜你，本来想借着你搭讪个妞，你TM就会踪着老太太屁股后面走，看见美女摸你你就拉屎。你说你是不是bt。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&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;&nbsp;&nbsp; 我要不是属狗的我真把你扔火锅里吃了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 想减肥，天天饿着，有天实在忍不住了，买了7斤柿子，吃完中毒了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 花8块钱买一瑜加光盘，练了4天，把脖子抻了，现在2肩膀还不一样高，女的看见我都说我是臭bt。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 夜里想玩点浪漫，自己给自己做烛光晚餐，结果把被子点着了。我妈以为我是因为失恋要z焚，给我送心理医院呆了2天。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实在孤独，花1块5买一大眼泡金鱼，买来之后就挺着肚皮在水里一动不动。我一直以为它死了，有天尿完尿，顺手扔厕所里，这孙子在尿里游的那叫一个欢啊，实在不忍心给它冲茅坑里，下手从尿里给捞出来了。结果手开始脱皮，到现在还没好。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 吃炒饼吃出啤酒盖，吃馄饨吃出脚指甲。做公交车被门夹脑袋，打苍蝇手拍钉子上，买股票就没涨过，去白云观烧烧香，手机掉功德箱里拿不出来。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出门口一和尚说我大富大贵，就是现在走背字，一高兴花570块钱买了他一个翡翠护身符，让我天天含嘴里，有一天哥们来了说我舌头怎么绿了，我把翡翠拿出来一看原来是一大玻璃，哥们说：你见过道观里有和尚吗？我想想也是，孙子你骗我就骗把，还他妈非让我天天叼着，现在一伸舌头人家以为我他妈苦胆破了，你说那个妞能理我。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 天天做噩梦，不是被人宰了，就是让动物给j了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 想老老实实在家看会电视，tm台台演《奋斗》10几个美女围着一叫陆涛的转，爱的死去活来，TM大房子，大美妞，有几十个亿的大爸爸。临了你丫还说：我要的不是这个。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 和着我同龄人都是这么过日子啊，换个台把：又来一许三多天天嚷嚷做有意义的事，昨天还心志不全呢，今天就抗一大狙去缅甸崩毒贩子，可能吗？三多，我告诉你，我叫王大鸡儿，我是铁姑娘团的，你信吗？真TM想把电视砸了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上校友录想寻摸2个人吃剩下的妞，我小学女的全结婚了，加中学大学班级，结果不让我通过，说我上学那会是什么不良少年，我TM都奔三张了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就刚才写帖子，跳闸一次，电脑自动关机2次，烟抽没了，垃圾桶里捡烟屁抽，手还让一按钉扎了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我只是希望回帖的开开心心，09年走好运而已，不回帖的一样交好运啊。 
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7895/</link>
<title><![CDATA[网易说：《魔兽世界》测试任务完成啦！]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Mon, 07 Sep 2009 02:25:05 +0000</pubDate> 
<guid>http://www.niuc.net/post/7895/</guid> 
<description>
<![CDATA[ 
	《魔兽世界》中文官方网站于2009年9月5日发布了新的公告通报游戏测试进展。以下为公告原文：<br/><br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">亲爱的玩家，<br/><br/>对于大家在《魔兽世界》过渡期间的耐心和支持，我们再次表示诚挚的谢意。自7月30日免费内测至今，已有数百万玩家回归艾泽拉斯，帮助我们充分测试全新的硬件设施。我们对硬件设施的稳定和表现一直感到很满意，并相信在得到政府批准投入正式运营后，定能在未来几年里为广大玩家提供一流的游戏体验。<br/><br/>早在六月，我们已承诺向现有老玩家回馈一定的免费游戏时间，以感谢他们在过渡期间的忠实支持。现在测试的任务业已完成，为履行此前的承诺，今天我们宣布：从9月6日起直至9月14日,现有玩家可继续体验8天的免费游戏，即从6月7日到7月30日停服期间每停服一周回馈一天的免费游戏时间。<strong>若我们在上述日期前获得正式运营的批准，我们将立即开通新帐号的注册，但新加入的玩家将不能免费游戏。</strong><br/><br/>感谢您对《魔兽世界》一如既往的热情支持。希望通过官方网站www.warcraftchina.com，尽快与大家分享有关正式运营的消息。<br/><br/><p align="center">《魔兽世界》运营团队<br/><br/>2009年9月5日</p></div></div><br/><br/>以上公告中，加粗的语句，让我依然觉得，网易还没能控制一切，那是否代表，广大玩家，又得面临新一轮的关服呢？<br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7894/</link>
<title><![CDATA[深度分析网络游戏运营手段]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Sat, 05 Sep 2009 05:46:18 +0000</pubDate> 
<guid>http://www.niuc.net/post/7894/</guid> 
<description>
<![CDATA[ 
	　　如同商场的促销一样，网络游戏的“运营”通常时候通过线下、线上活动通常是以聚集人气和短时间促销为最主要的目的的。正所谓买的没有卖的精明——笔者身在游戏业内也曾策划和参与了许多的游戏活动。今天就在这里针对国内最为主要的几种游戏活动进行一定的介绍，希望玩家们能搽亮双眼有选择地参与从而更多地体验游戏的乐趣和里面的实惠。<br/><br/>　　<strong>一、 什么是网络游戏里的“运营活动”？ </strong> <br/><br/>　　在前面已经讲了其实网络游戏里的“运营活动”在很大程度上跟商场的促消一样是拥有一定的共性。而其实游戏的活动也正是营销组合中4P的Promotion(促消）——指企业要运用广告、人员促消公共宣传和销售推广等各种手段将产品尽多、尽快地转移到顾客手中。&nbsp;&nbsp;<br/><br/>　　不过跟一般传统的市场营销不同的是现阶段在其它传统行业的“运营活动”概念还仅限我们通常看到的买N送N、打折、返卷来达到刺激消费的作用，而网络游戏中的活动通常是以其游戏所在的整个虚拟社会为背景去通过采用沟通、比赛等更具有互动性的娱乐方式来达到目的的——更多的乐趣，是跟传统促消仅仅以给消费者更多的实惠不同的。而随着中国乃至世界网络游戏的不断成长这种针对游戏的全方位“运营活动”也出现了更多、更新的类型。而许多网络游戏也正是通过“运营活动”来达到促进游戏内消费和维持甚至提高在线人数的法宝。&nbsp;&nbsp;<br/><br/>　　<strong>二、几种常用的“手段”类型</strong> <br/><br/>　　其实针对网络游戏里的各种活动，我们还无法从教材等学术方面来正面讨论，因为在中国对于网络游戏制作的教材就非常少，何况本身就可能被许多人忽略的“活动”？所以以下我们就尽量收集现在在国内最常用的几个“活动”类型来进行一定的分析。&nbsp;&nbsp;<br/><br/>　　<strong>1）美女、代言人当道的 </strong> <br/><br/>　　不知道从什么时候开始邀请美女和明星作为游戏的代言人简直成为了每款游戏在推出前、推出中、推出后所必备的。&nbsp;&nbsp;<br/><br/>　　其实这些代言人可能本身就不玩自己所代言的游戏，甚至根本就不玩游戏。而每次请这样的人来代言，如果仅仅是突然成名的美女到还是好说——直接把该美女变成跟自己签约的员工，发点工资适当给点其他的代言费就够用了。而如果请名人，那就是花多少钱都没准了，而且一个二线以上的名人代言的产品有很多。即使你签下他，也不能保证他能每次都出席你安排的活动，同时一个名人由于身上代言了许多产品，搞的玩家也往往不记得，他到底都代言了什么。&nbsp;&nbsp;<br/><br/>　　所以名人代言对于普通用户通常会看到三个结果：1、实在无法把本身就是有很多品牌的商品跟众多代言人划上正确的等号——这在几前前国内疯狂地推各种运动品牌，纷纷请了港台几乎所有艺人，而用户还是搞不清楚哪个运动牌好是一样的。2、由于一个明星可能代言的牌子实在太多了，所以用户可能容易忽视其中那个公众暴光率最低的品牌（而由于国内现在无法在电视媒体上做游戏广告）。这使得游戏所请的代言人经常是花费不小，而效果一般。3、也是最差的效果了——自己请的代言人居然成了代言杀手，代言一个品牌则死一个。在这里我们就不点名了！&nbsp;&nbsp;<br/><br/>　　<strong>2）征名、征文、征所有跟游戏相关的东西</strong> <br/><br/>　　国内的游戏厂商貌似非常尊重玩家的选择。许多游戏从刚刚签下代理协议开始，就期望着玩家能给自己的游戏起个好名字。无论是爱情的的还是打仗打到太空的，无论是史前题材的还是未来世界的游戏。厂商都会拿出PSP、PS2等各种诱人的奖品来让玩家给自己的游戏起名字。但是，尽管如此我们还是只能从众多、另类、有创意的名字中看到的还是诸如“**前夜”这样跟游戏毫无关系的游戏名字。&nbsp;&nbsp;<br/><br/>　　中国向来是不缺乏写手的。这点不仅仅包括我等小枪手，更有许多玩家会把自己对游戏的真正建议发在论坛上。于是官方发现，征文成为了一个不错的选择。我就在自己公司挑选过玩家的投稿。所实话，在众多文章中文笔好的真是不多，而很不幸的是往往官方所挑选文章的标准往往会把这类稿件先淘汰掉。不可否认，每款游戏都有自己的弱点，而真正喜欢这款游戏的玩家往往会殷切地、无意思地把这类缺点去扩大话。而这也正是游戏官放所不愿意看到的——所以，在种种指标下，我们选出来的只能剩下《我在某某游戏中愉快的一天》、《某某游戏改变了我的一生》这类连我们这些当过枪手的人看了也相当、相当汗的文章！&nbsp;&nbsp;<br/><br/>　　<strong>3）现场活动 </strong> <br/><br/>　　说到线上活动，也许我们能想出很多种。那么我在没把所有线上活动介绍完之前，先介绍下线下活动吧。&nbsp;&nbsp;<br/><br/>　　其实大多数的线下活动基本上都属于现场活动。此类的现场有很多种，小到各高校里发点卡和海报的宣传人员组成的阵地，大到CHINAJOY上花费能高达百万的展台和活动。说到这里，要首先表扬下现场活动做的比较出色的盛大了——《泡泡堂》在在开放内测一段时间之后，峰值同时在线人数只有一万左右。同期，《疯狂坦克2》已经开始商业化，开始包月类型的收费。《泡泡堂》的市场宣传和活动策划也开始有了重点倾向，“爱情双响泡”就是当时十分受欢迎的活动之一。市场人员已经把握到《泡泡堂》游戏的突出之处，开始着重推荐“女性、双打”这两个关键词。而后来又通过推出自己的“亲子对对碰”、“相约泡泡堂，非常男女对抗赛”等能够跟线上活动相辅助的线下活动，几乎帮《泡泡堂》这样一款低成本制作的游戏打造成为国内休闲网络游戏的一个奇迹。&nbsp;&nbsp;<br/><br/>　　坦率的说，国内的大部分游戏公司的市场人员，在进行线下活动策划的时候都不够专业。而同样的话，如果毫不客气地说，这类人员根本就不懂得游戏，他们同时更不懂得去尊重玩家。所以，我们看到国内大部分网络游戏的线下活动，都是以大投入，低回报来结束的。试想，一个只会发娃娃，发点卡，发海报的展台怎么能吸引玩家过来游戏呢——文章发表的时候估计最新的CHINAJOY又要开始了吧，细心的读者如果能亲临现场的话，也许能看到类似的场景。&nbsp;&nbsp;<br/><br/>　　<strong>4）做任务得奖励</strong>&nbsp;&nbsp;<br/><br/>　　游戏内活动其实包含的内容就非常广阔了。那么在这里我就主要介绍下国内游戏厂商经常使用的活动项目。&nbsp;&nbsp;<br/><br/>　　一种就是完成游戏内任务获得某奖励。这类活动大多是在某些特定的日子内举办的，玩家可以通过参与游戏内的某些活动来获得奖励，这其实一个非常人性话的操作，而且大部分玩家也会非常喜欢，并且改类型的活动经常能在活动当天把自己的总的在线游戏人数推到一个新的高峰。如果该活动利用的好，则可能能保证游戏对于玩家的粘着度。但是，该游戏规则的设计者往往会在很多细节上计划的不够全面。&nbsp;&nbsp;<br/><br/>　　首先，官方往往要求玩家在活动开始的前多少天就要报名，并且给玩家在当天约定一个比较苛刻或者不大容易接受的时间；其次，不知道出于什么原因，同类型的活动玩家会发现在看过一篇天花乱坠的宣传后对于游戏规则还不是很了解，这使得玩家即使参加了活动也会容易出现一头雾水的场面；再次，游戏内玩家并不能第一时间找到游戏中的GM，从而及时地得到开始游戏——我就在一次自己公司举行的游戏中，听说要搞活动了，结果在大厅站了2个多小时看到的都是互相询问的玩家而看不到一个GM站出来为大家解答疑问；最后，就是奖励了。说实话由于游戏内的任务通常比较容易完成，所以官方在给的奖励通常是非常微不足道的，略显吝啬了。当然，这应该算不上缺点了，我只是提玩家们抱怨一下。&nbsp;&nbsp;<br/><br/>　　<strong>5）改变游戏特性，做活动</strong>&nbsp;&nbsp;<br/><br/>　　在以前MMORPG就是砍怪、练级为主的，后来有增加了帮会战争、PK等。即使如此，增加的游戏类型都属于该游戏本身的范畴里面。不过，我们现在经常能看到玩家可以在MMORPG里打斗地主，在〈QQ堂〉里踢足球了。我们先暂时不去评论这种游戏中的游戏制作的水准如何，但是有这种为了自己的玩家能享受到更多乐趣的做法当然是可圈可点的。&nbsp;&nbsp;<br/><br/>　　不过，如果一款游戏如果过于利用这种改变游戏本身的特性，而以获得利益为目的的话，那就非常应该去鄙视它。笔者就见过身边的一个玩家在游戏里的赌场把自己在游戏中的钱财和游戏外的现金都输的差不多了……&nbsp;&nbsp;<br/><br/>　　作为一个长期存在游戏中的项目，其实已经不能完全称之为线上活动了，它更像是游戏的一个扩展，不过商家如果仅仅是为了增加该游戏的收入而设立的话，则未免有点欺诈消费者的嫌疑了。&nbsp;&nbsp;<br/><br/>　　<strong>6）免费或者送点卡给你玩</strong>&nbsp;&nbsp;<br/><br/>　　虽然现在有越来越多的游戏是免费运营了，但是每款收费网游戏也是从最早的免费内/公测开始的。为了能够在游戏初期除了个别非常牛气的游戏，都实行了注册帐号免费试玩若干天甚至直接把点卡和客户端送到你的手上。&nbsp;&nbsp;<br/><br/>　　不过这里就要说到官方的一个不厚道了：1、由于免费的帐号可能是玩家在内测或者公测的时候注册的，所以基本上所有的玩家都会面临游戏正式运营后的删号处理。笔者就，曾经就非常辛苦的在玩了一款卡丁车后，突然有一天发现自己所有的个人信息都被清掉了，甚至连当时注册的昵称也没了；2、由于赠送的点卡大多是跟帐号捆绑的，所以玩家注定玩光该游戏所有的点数后，要么就是去冲值要么就是再去搞个免费的号来。不过如果你是续费的话，那么问题又来了——由于ID是免费卡上送的而且不能更改，所以你必须记住一个古怪毫无个性的ID才能继承之前的游戏资料。&nbsp;&nbsp;<br/><br/>　　其实长久地看来几乎所有送的点卡和新ID能最后被玩家上到网上去真正使用的还是极少数，而这些极少数的玩家也大多在2个小时的游戏时间后就再不玩了（个别牛的很的游戏除外）。所以这样一个活动经常是商家和玩家的双败——不过，这也是在游戏竞争激烈的情况下商家为了保证前期的在线人数而经常做的。&nbsp;&nbsp;<br/><br/>　　<strong>7）借题发挥型</strong>&nbsp;&nbsp;<br/><br/>　　每款游戏从开始就面临着各种各样的问题，这无论大作、小作都是一样的。而一个聪明的游戏运营商，能够在保证自己利益的前提下很好的去利用这类的问题。&nbsp;&nbsp;<br/><br/>　　如，打击外挂、净化游戏环境都成为商家宣传自己的好噱头。不过我们已经看到了太多的厂商总是把自己所发挥的“题”放在一个相对并不是最重要的角落，而仅仅是为了去宣传自己。&nbsp;&nbsp;<br/><br/>　　另外几乎每款游戏都拥有自己出色的枪手，他们能够抓住一个很小很小的契机然后大做文章，而这类通过把微不足道事件去扩大化的做法，往往只能让看到的玩家短暂停留，而不是长期驻留在那里。所以，无论你如何发挥如果都是走在一个夸大事实的基础上，那么到最后损失的仍旧是商家自己。 <br/><br/><br/>　　<strong>三、此类的“手段”是否能达到目的？</strong>&nbsp;&nbsp;<br/><br/>　　为了能争到更多的游戏玩家，在更段的时间收回成本甚至赢利。商家必须“不择手段”，但是现如今能够持续发展的运营手段，必须是要求用户和卖家都要能达到“双赢”的。如果仅仅是选择参加自己的游戏能获得POLO、PSP虽然能在一定程度上吸引到一定量的玩家，但是给大部分玩家的感觉总是别人早就“先到先得”了，而跟自己“毫无瓜葛”。&nbsp;&nbsp;<br/><br/>　　当然，无论商家是如何去实现自己的“运营活动”都是会从自己的利润或者成本里提取一定的量来汇报用户的。但是笔者就看到过一份榜单上居然所有的获奖名单居然跟某高校入校学生完全吻合，这种低级的巧合作为玩家来说真的也没什么话好多说了。&nbsp;&nbsp;<br/><br/>　　而那种，以做活动或者增加游戏内容在游戏中来敛取钱财的作法就更为低劣了……&nbsp;&nbsp;<br/><br/>　　总的来说，国内大多数的游戏厂商在游戏的“运营”过程中，许多做法都并不是十分的高明，而仅仅是简单的互相抄袭。这也使得，我们很难看到让玩家和商家都高兴的活动——当然，这也跟国内此类直接设计人员的总体素质并不是十分高而有关的！&nbsp;&nbsp;<br/><br/>　　<strong>四、一个正确的“运营活动”从策划的实施</strong>&nbsp;&nbsp;<br/><br/>　　<strong>1）目标消费群的确立</strong>&nbsp;&nbsp;<br/><br/>　　在做任何一件事情，我们都必须明白我们这件事情是给谁做的，才能控制好自己做活动的量和度。从而能通过最简洁和有效的手段把自己的活动宣传到他们的耳朵和眼睛里，并且把他们吸引到你策划的活动中来。&nbsp;&nbsp;<br/><br/>　　<strong>2）活动的设计</strong>&nbsp;&nbsp;<br/><br/>　　很早很早以前有句话叫“人有多大胆，地有多大产”。这样的话也许偏激，但是应用在游戏的活动中还是非常有借鉴的意义了。现在国内的许多策划在制定活动的时候，考虑的总是过多——这直接导致了同类型活动的泛滥，缺乏新意。很难达到应有和需要的效果。&nbsp;&nbsp;<br/><br/>　　所以一个活动的设计将对整个游戏的成功与否其着不可忽视的作用。比如：《泡泡堂》当年设计自己的游戏可以在一个键盘上同时玩两个帐号就非常的吸引，这也必然引来了不少情侣玩家。而，至今国内还是没有类似的情侣游戏。&nbsp;&nbsp;<br/><br/>　　<strong>3）明白自己的游戏</strong>&nbsp;&nbsp;<br/><br/>　　这个要求看起来似乎很搞笑——自己公司的策划怎么会不了解自己的游戏呢？在这里我就可以很负责地告诉大家，许多游戏公司的相关人员可能根本就没有玩过自己的游戏。笔者就看到，某国内著名游戏公司强制要求自己的员工是不得在单位的任何时候游戏的。（这倒是跟欧美很多游戏公司的要求相反）&nbsp;&nbsp;<br/><br/>　　而也往往就是这样一群对自己的游戏，甚至所有游戏都不甚了了的人设计出了许多“活动”。那我们也可以想象，一个连自己的不了解的人怎么能吸引别人呢？ <br/><br/>　　<strong>4）预估能力</strong>&nbsp;&nbsp;<br/><br/>　　随着国内游戏企业越来越多，越来越成熟。我们发现太多的游戏公司已经缺乏了一个基本的判断能力了。所以，不少“活动”不是做的不到位，就是做的过了。&nbsp;&nbsp;<br/><br/>　　如果您的游戏本身就品质很高，那么很可能你的活动能吸引非常多的玩家。而这个时候面对比平时要高出几何倍的服务器压力，这就要求官方必须有足够的服务器承载度，足够的GM和客服人员等与之配套的措施。而如果您的游戏即使在开展了活动后，也可能维持不到5000人的同时在线，我这里就劝你最好先把游戏关了——不过如果你一定做下去的话，那么我想你应该有效地控制自己的宣传成本，因为对于这样的游戏我想你需要把更多的精力放在游戏本身质量的提高上，而不是简单地把玩家骗到游戏中来。&nbsp;&nbsp;<br/><br/>　　<strong>后记</strong>&nbsp;&nbsp;<br/><br/>　　笔者一直在游戏公司里从业，由于一直没有非常正式地参与到游戏的“运营”中来。但是,看到许多自己公司或者别的公司在运营或者做市场的过程中走入了许多误区甚至在做许多完全不应该的事情。&nbsp;&nbsp;<br/><br/>　　整体来说在国内的所有游戏公司中，我们所做的都是健康的、积极的。很少出现一些以骗玩家为目的的事情。所以，本文中并没有对一些不良的事情去大加渲染而把他们形容成“黑幕”。&nbsp;&nbsp;<br/><br/>　　一款游戏的成功与否仍旧是以该游戏的品质来左右的。这也是我一直坚持的观点，而“运营”仅仅是为了能够更好的去服务于游戏，让自己的游戏能够更加吸引玩家。本文是在国内许多游戏商家大多以代理为主的现状下，希望能给彼此一定的借鉴！<br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E6%25B8%25B8%25E6%2588%258F/" rel="tag">游戏</a> , <a href="http://www.niuc.net/tags/%25E8%25BF%2590%25E8%2590%25A5/" rel="tag">运营</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7893/</link>
<title><![CDATA[千万别吓到了，00后比90后要狠多了！]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Fri, 21 Aug 2009 03:40:42 +0000</pubDate> 
<guid>http://www.niuc.net/post/7893/</guid> 
<description>
<![CDATA[ 
	不说那么多，直接上片！<br/><br/><object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/4Bfqj6U6FgA"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/4Bfqj6U6FgA" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br/><br/>再补张图，牛得很，别雷到了！<br/><br/><a href="http://www.niuc.net/attachment.php?fid=279" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=279" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>Tags - <a href="http://www.niuc.net/tags/90%25E5%2590%258E/" rel="tag">90后</a> , <a href="http://www.niuc.net/tags/00%25E5%2590%258E/" rel="tag">00后</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7892/</link>
<title><![CDATA[巫妖王之怒并未向新闻出版局申报!]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 20 Aug 2009 07:26:31 +0000</pubDate> 
<guid>http://www.niuc.net/post/7892/</guid> 
<description>
<![CDATA[ 
	　　8月20日上午消息，北京市新闻出版局在其官方网站发布公告称，尚未接到《魔兽世界》(以下简称“魔兽”)新资料片“巫妖王之怒”游戏资料的申报材料，之前上报的“燃烧的远征”正在新闻出版总署的受理审批之中。<br/><br/>　　此前有媒体报道，北京市新闻出版局在网站回答玩家咨询时表示，已将“巫妖王之怒”上报至新闻出版总署接受审批，北京市新闻出版局公告对此进行了否认。<br/><br/>　　网易于7月30日凌晨开启魔兽内测，当时预计内测时间为期一周。由于“燃烧的远征”至今仍未通过申请，原定内测截止日期前一天，网易表示将视情逐日延长内测时间，直至最终获得政府批准重新投入商业运营。(向东)<br/><br/>　　以下为公告全文：<br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">　　北京市新闻出版局关于网络游戏《魔兽世界》出版情况的说明<br/><br/>　　近来，我局不断接到游戏玩家、游戏爱好者等许多关心和支持我国游戏产业发展的热心人士的咨询电话和电子邮件，主要内容是关于该款游戏的版本内容和审批进度的具体情况。对此，我局特别说明如下：<br/><br/>　　2009年6月2日，我局接到北京青鸟科教电子出版社有限公司关于引进出版《魔兽世界》网络游戏的申请。该款游戏的版本是v3.1.0，即业内人士所说的“燃烧的远征”。目前，该款游戏正在新闻出版总署的受理审批之中。<br/><br/>　　另外，我局没有接到“魔兽世界：巫妖王之怒”游戏资料的申报材料。<br/><br/>　　感谢广大朋友对我局各项工作的热情关心和大力支持！我局将认真履行政府职能，依法行政，切实为大家服好务。<br/><br/>　　特此说明。<br/><br/>　　北京市新闻出版局<br/><br/>　　2009年8月18日</div></div><br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7891/</link>
<title><![CDATA[门户网站也不见得安全啊：国家互联网应急中心称搜狐天涯阿里等被挂木马]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 13 Aug 2009 15:27:46 +0000</pubDate> 
<guid>http://www.niuc.net/post/7891/</guid> 
<description>
<![CDATA[ 
	8月13日下午消息，国家互联网应急中心网站发布公告，称检测发现搜狐、天涯社区、阿里巴巴等国内三家网站存在挂马页面，有可能造成用户敏感数据失窃，也有可能形成大规模僵尸网络，严重威胁互联网运行安全。<br/><br/>　　国家互联网应急中心网站公告显示，根据安天信息技术有限公司CNCERT检测数据，搜狐、天涯社区、阿里巴巴等国内三家网站存在挂马页面。用户在没有做好系统防护的情况下访问相关页面，浏览器就会自动下载恶意代码在计算机上执行，这不仅可能造成用户敏感数据失窃，也有可能形成大规模僵尸网络，严重威胁互联网运行安全。<br/><br/>　　鉴于上述网站用户访问量较大，CNCERT提醒互联网用户不要访问挂马页面，并安装好防护软件，做好系统加固。此外CNCERT建议有关网站所属公司立即清除挂马页面，并加强自身运营的网站及业务系统的安全管理，以免对广大互联网用户安全造成严重威胁。<br/><br/>　　另据最新监测显示，截至目前上述三家网站被挂马页面已经清除。<br/><br/>　　以下为国家互联网应急中心网站发布的公告：<br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">　　关于搜狐、天涯社区以及阿里巴巴等门户网站存在挂马页面的公告(更新)<br/><br/>　　安全公告： CN-SA09-08<br/><br/>　　发布日期：2009年8月12日<br/><br/>　　事件类型：挂马<br/><br/>　　威胁评估： 中<br/><br/>　　事件描述：<br/><br/>　　8月11日，CNCERT监测发现搜狐、天涯社区、阿里巴巴等国内三家大型门户网站存在挂马页面。用户在没有做好系统防护的情况下访问相关页面，浏览器就会自动下载恶意代码在计算机上执行，这不仅可能造成用户敏感数据失窃，也有可能形成大规模僵尸网络，严重威胁互联网运行安全。截至8月12日12时，阿里巴巴、天涯社区网站的挂马页面仍然存在；搜狐网站的页面在11日下午清除后于12日上午再次被挂马。<br/><br/>　　鉴于上述网站用户访问量较大，CNCERT提醒互联网用户不要访问挂马页面，并安装好防护软件，做好系统加固。此外，CNCERT建议有关网站所属公司立即清除挂马页面，并加强自身运营的网站及业务系统的安全管理，以免对广大互联网用户安全造成严重威胁。<br/><br/>　　如果发现有类似事件发生，请向CNCERT举报，联系电话：01082990999，邮箱：cncert@cert.org.cn。</div></div><br/><br/>　　<strong>附：搜狐、天涯社区、阿里巴巴网站的挂马页面链接（在无法确认安全的情况下请勿打开）</strong><br/><br/>　　http://digi.it.sohu.com/20070918/n252211346.shtml(搜狐数码频道)<br/><br/>　　http://liuxue.sohu.com/sgp/ (搜狐留学频道)<br/><br/>　　http://info.china.alibaba.com/news/detail/v5003013-d1000221193.html(阿里巴巴商业资讯频道)<br/><br/>　　http://cache.tianya.cn/publicforum/Content/music/1/123173.shtml(天涯社区音乐天地版面)。<br/><br/>　　注：8月13日上午9时，CNCERT监测到天涯社区挂马页面仍然存在，阿里巴巴、搜狐挂马页面已清除；经过CNCERT积极协调，天涯社区于13日下午15点30分清除挂马页面。<br/><br/>　　<strong>信息提供者：</strong><br/><br/>　　CNCERT/CC<br/><br/>　　哈尔滨安天信息技术有限公司<br/><br/>　　<strong>挂马简介：</strong><br/><br/>　　挂马就是黑客入侵了一些网站后，将自己编写的网页木马嵌入被黑网站的主页中，利用被黑网站的流量将自己的网页木马传播开去，以达到自己不可告人的目的。<br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E5%25AE%2589%25E5%2585%25A8/" rel="tag">安全</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7890/</link>
<title><![CDATA[符合SEO优化标准的HTML代码布局]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Seo技术]]></category>
<pubDate>Thu, 13 Aug 2009 08:23:33 +0000</pubDate> 
<guid>http://www.niuc.net/post/7890/</guid> 
<description>
<![CDATA[ 
	本文详细介绍了如何布局HTML，使之能更符合SEO要求！<br/>............<br/><br/>Tags - <a href="http://www.niuc.net/tags/seo/" rel="tag">seo</a> , <a href="http://www.niuc.net/tags/seo%25E4%25BC%2598%25E5%258C%2596/" rel="tag">seo优化</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7889/</link>
<title><![CDATA[巫妖王之怒已经上报总署]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Thu, 13 Aug 2009 01:29:05 +0000</pubDate> 
<guid>http://www.niuc.net/post/7889/</guid> 
<description>
<![CDATA[ 
	北京新闻出版局11日透露，网易《巫妖王之怒》已经上报新闻出版总署，总署已经受理。<br/><br/>详细看图：<a href="http://www.niuc.net/attachment.php?fid=278" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=278" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>在此之前，曾有消息称，网易二度送审的修正版《魔兽世界》审批再次遇阻，网易将提交<strong>第三次</strong>修改版本。<br/><br/>截止目前，网易魔兽世界仍然在内测中，具体正式运营日期仍未确定。<br/><br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7888/</link>
<title><![CDATA[再度失望：网易二度送审遇阻，魔兽内测前途难卜]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Wed, 12 Aug 2009 04:11:45 +0000</pubDate> 
<guid>http://www.niuc.net/post/7888/</guid> 
<description>
<![CDATA[ 
	　　魔兽世界内测已经10余天的时间，但版署方面的审批仍没有结果。据消息称，<strong>网易数日前第二次送审的修正版《魔兽世界》再次遇阻，可能发现新问题。这次遇阻将使《魔兽世界》前途未卜，甚至导致该游戏内测终止，再度陷入停服。</strong><br/><br/>　　据媒体报道，有可靠渠道消息称，网易二度送审的修正版《魔兽世界》审批再次遇阻，这也意味着网易第二次修正提交版未能完成审批重任。<br/><br/>　　事已至此，尽管目前新闻出版署允许网易先行内测，但如果游戏审批中发现重大问题，则该游戏仍将面临内测许可被收回的尴尬。当然，另一种可能性相对更大，即如果审批中并非遇到关键原则性问题，版署应该允许网易继续内测，并重新提交新的修改版本。考虑到《魔兽世界》已经在大陆运营超过4年的时间，如有重大问题，应该早已发现，因此，网易再度提交修改版的可能性更大。相信网易将在数日内将修正版本第三次内容送审。<br/><br/>　　网易7月30日开启《魔兽世界》内测。停服50余天的魔兽终于变相开服，但内测期间网易需要满足包括：免费对已拥有魔兽账号的玩家开启登陆游戏，但不开放新的魔兽账号注册，不得向内测玩家收费等要求。<br/><br/>　　在为期一周的内测截止日期前，网易再度公告称，将“逐日延长”内测，并没有再度限制该游戏的内测截止日期。该公告称，“我们向有关政府部门提交了又一个修改版本，针对上一轮内容修改的反馈意见作出了相应微调，希望能很快得到内容审查结果。”<br/><br/>　　另有报道称，版署方面曾表示对网易《魔兽世界》的审批没有时间限制。根据版署的审批规定,审批过程中要求修改的不计入正常的审批日限中。也因此，如果版署提出修改要求，并不需要网易再次重新启动审批，将按照中断的流程继续并将内容审查的部分流程修正。<br/><br/>　　《魔兽世界》的前途如何，真的难以预料，开，估计肯定是能开，但是，开了后，人还能留下多少呢？<br/>Tags - <a href="http://www.niuc.net/tags/%25E9%25AD%2594%25E5%2585%25BD%25E4%25B8%2596%25E7%2595%258C/" rel="tag">魔兽世界</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/alias/java-and-csharp-comparison/</link>
<title><![CDATA[Java和C#的语法对照（Java (J2SE 5.0) and C# Comparison）]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Dot-Net技术]]></category>
<pubDate>Tue, 11 Aug 2009 07:23:36 +0000</pubDate> 
<guid>http://www.niuc.net/alias/java-and-csharp-comparison/</guid> 
<description>
<![CDATA[ 
	<table border="1" cellspacing="0" cellpadding="0"><TR align="middle"><TD colSpan="2"><TABLE id="Table2" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Program Structure</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR><TD>package hello;<BR><BR>public class HelloWorld {<BR>&nbsp;&nbsp; public static void <STRONG>main</STRONG>(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String name = "Java";<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// See if an argument was passed from the command line<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (args.length == 1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name = args[0];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Hello, " + name + "!");<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>} </TD><TD>using System; <BR><BR>namespace Hello {<BR>&nbsp;&nbsp; public class HelloWorld {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void <STRONG>Main</STRONG>(string[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string name = "C#";<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // See if an argument was passed from the command line<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (args.Length == 1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name = args[0];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("Hello, " + name + "!");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp; }<BR>} </TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table2" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Comments</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR><TD>// Single line<BR>/* Multiple<BR>&nbsp;&nbsp;&nbsp;&nbsp;line&nbsp;&nbsp;*/<BR>/** Javadoc documentation comments */</TD><TD>// Single line<BR>/* Multiple<BR>&nbsp;&nbsp;&nbsp;&nbsp;line&nbsp;&nbsp;*/<BR>/// XML comments on a single line<BR>/** XML comments on multiple lines */</TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table3" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Data Types</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD><p>Primitive Types<BR>boolean<BR>byte<BR>char<BR>short, int, long<BR>float, double</p><p><BR>Reference Types<BR>Object&nbsp;&nbsp; (superclass of all other classes)<BR>String<BR><EM>arrays, classes, interfaces</EM></p><p>Conversions </p><p>// int to String <BR>int x = 123; <BR>String y = Integer.toString(x);&nbsp;&nbsp;// y is "123"</p><p>// String to int<BR>y = "456"; <BR>x = Integer.parseInt(y);&nbsp;&nbsp; // x is 456</p><p>// double to int<BR>double z = 3.5; <BR>x = <STRONG>(int)</STRONG> z;&nbsp;&nbsp; // x is 3&nbsp;&nbsp;(truncates decimal)</p></TD><TD><p>Value Types<BR>bool<BR>byte, sbyte<BR>char<BR>short, ushort, int, uint, long, ulong<BR>float, double, decimal<BR><EM>structures, enumerations</EM></p><p>Reference Types<BR>object&nbsp;&nbsp;&nbsp;&nbsp;(superclass of all other classes)<BR>string<BR><EM>arrays, classes, interfaces, delegates</EM></p><p>Convertions</p><p>// int to string <BR>int x = 123; <BR>String y = x.ToString();&nbsp;&nbsp;// y is "123"</p><p>// string to int<BR>y = "456"; <BR>x = int.Parse(y);&nbsp;&nbsp; // or x = Convert.ToInt32(y);</p><p>// double to int<BR>double z = 3.5; <BR>x = <STRONG>(int)</STRONG> z;&nbsp;&nbsp; // x is 3&nbsp;&nbsp;(truncates decimal)</p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table4" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Constants</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD>// May be initialized in a constructor <BR><STRONG>final</STRONG> double PI = 3.14; </TD><TD><STRONG>const</STRONG> double PI = 3.14;<p>// Can be set to a const or a variable. May be initialized in a constructor. <BR><strong>readonly</strong> int MAX_HEIGHT = 9; </p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table20" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Enumerations</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD><p><STRONG>enum</STRONG> Action {Start, Stop, Rewind, Forward};</p><p>// Special type of class <BR><STRONG>enum</STRONG> Status {<BR>&nbsp;&nbsp;Flunk(50), Pass(70), Excel(90);<BR>&nbsp;&nbsp;private final int value;<BR>&nbsp;&nbsp;Status(int value) { this.value = value; }<BR>&nbsp;&nbsp;public int value() { return value; } <BR>}; </p><p>Action a = Action.Stop;<BR>if (a != Action.Start)<BR>&nbsp;&nbsp;System.out.println(a);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Prints "Stop"<BR><BR>Status s = Status.Pass;<BR>System.out.println(s.value());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Prints "70" </p></TD><TD><p><STRONG>enum</STRONG> Action {Start, Stop, Rewind, Forward};</p><p><STRONG>enum</STRONG> Status {Flunk = 50, Pass = 70, Excel = 90};<BR></p><p>No equivalent.<BR><BR><BR><BR><BR><BR>Action a = Action.Stop;<BR>if (a != Action.Start)<BR>&nbsp;&nbsp;Console.WriteLine(a);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Prints "Stop"</p><p>Status s = Status.Pass;<BR>Console.WriteLine((int) s);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Prints "70"</p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table5" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Operators</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="16"><p>Comparison<BR>==&nbsp;&nbsp;&lt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&lt;=&nbsp;&nbsp;&gt;=&nbsp;&nbsp;!=</p><p>Arithmetic<BR>+&nbsp;&nbsp;-&nbsp;&nbsp;*&nbsp;&nbsp;/<BR>%&nbsp;&nbsp;(mod)<BR>/&nbsp;&nbsp; (integer division if both operands are ints)<BR>Math.Pow(x, y)</p><p>Assignment<BR>=&nbsp;&nbsp;+=&nbsp;&nbsp;-=&nbsp;&nbsp;*=&nbsp;&nbsp;/=&nbsp;&nbsp; %=&nbsp;&nbsp; &amp;=&nbsp;&nbsp;&#124;=&nbsp;&nbsp;^=&nbsp;&nbsp;&lt;&lt;=&nbsp;&nbsp;&gt;&gt;=&nbsp;&nbsp;&gt;&gt;&gt;=&nbsp;&nbsp;++&nbsp;&nbsp;--</p><p>Bitwise<BR>&amp;&nbsp;&nbsp;&#124;&nbsp;&nbsp;^&nbsp;&nbsp; ~&nbsp;&nbsp;&lt;&lt;&nbsp;&nbsp;&gt;&gt;&nbsp;&nbsp;&gt;&gt;&gt;</p><p>Logical<BR>&amp;&amp;&nbsp;&nbsp;&#124;&#124;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&#124;&nbsp;&nbsp; ^&nbsp;&nbsp; !</p><p><STRONG>Note:</STRONG> &amp;&amp; and &#124;&#124; perform short-circuit logical evaluations</p><p>String Concatenation<BR>+</p></TD><TD height="16"><p>Comparison<BR>==&nbsp;&nbsp;&lt;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&lt;=&nbsp;&nbsp;&gt;=&nbsp;&nbsp;!=</p><p>Arithmetic<BR>+&nbsp;&nbsp;-&nbsp;&nbsp;*&nbsp;&nbsp;/<BR>%&nbsp;&nbsp;(mod)<BR>/&nbsp;&nbsp; (integer division if both operands are ints)<BR>Math.Pow(x, y)</p><p>Assignment<BR>=&nbsp;&nbsp;+=&nbsp;&nbsp;-=&nbsp;&nbsp;*=&nbsp;&nbsp;/=&nbsp;&nbsp; %=&nbsp;&nbsp;&amp;=&nbsp;&nbsp;&#124;=&nbsp;&nbsp;^=&nbsp;&nbsp;&lt;&lt;=&nbsp;&nbsp;&gt;&gt;=&nbsp;&nbsp;++&nbsp;&nbsp;--</p><p>Bitwise<BR>&amp;&nbsp;&nbsp;&#124;&nbsp;&nbsp;^&nbsp;&nbsp; ~&nbsp;&nbsp;&lt;&lt;&nbsp;&nbsp;&gt;&gt;</p><p>Logical<BR>&amp;&amp;&nbsp;&nbsp;&#124;&#124;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&#124;&nbsp;&nbsp; ^&nbsp;&nbsp; !</p><p><STRONG>Note:</STRONG> &amp;&amp; and &#124;&#124; perform short-circuit logical evaluations</p><p>String Concatenation<BR>+</p></TD></TR><TR><TD colSpan="2"><TABLE id="Table6" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Choices</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="163"><p>greeting = age &lt; 20 <STRONG>?</STRONG> "What's up?" <STRONG>:</STRONG> "Hello";</p><p><STRONG>if </STRONG>(x &lt; y) <BR>&nbsp;&nbsp;System.out.println("greater");</p><p><STRONG>if </STRONG>(x != 100) {&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;x *= 5; <BR>&nbsp;&nbsp;y *= 2; <BR>} <BR><STRONG>else</STRONG> <BR>&nbsp;&nbsp;z *= 6;</p><p>int selection = 2;<BR><STRONG>switch</STRONG> (selection) {&nbsp;&nbsp;&nbsp;&nbsp; <em>// Must be byte, short, int, char, or enum</em><BR>&nbsp;&nbsp;<STRONG>case</STRONG> 1: x++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>// Falls through to next case if no break</em><BR>&nbsp;&nbsp;<STRONG>case</STRONG> 2: y++;&nbsp;&nbsp; <STRONG>break;</STRONG> <BR>&nbsp;&nbsp;<STRONG>case</STRONG> 3: z++;&nbsp;&nbsp; <STRONG>break;</STRONG> <BR>&nbsp;&nbsp;<STRONG>default:</STRONG> other++;<BR>} </p></TD><TD height="163"><p>greeting = age &lt; 20 <STRONG>?</STRONG> "What's up?" <STRONG>:</STRONG> "Hello";</p><p><STRONG>if </STRONG>(x &lt; y)&nbsp;&nbsp;<BR>&nbsp;&nbsp;Console.WriteLine("greater");</p><p><STRONG>if </STRONG>(x != 100) {&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;x *= 5; <BR>&nbsp;&nbsp;y *= 2; <BR>} <BR><STRONG>else</STRONG> <BR>&nbsp;&nbsp;z *= 6;<BR><BR>string color = "red";<BR><STRONG>switch</STRONG> (color) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>// Can be any predefined type</em><BR>&nbsp;&nbsp;<STRONG>case</STRONG> "red":&nbsp;&nbsp;&nbsp;&nbsp;r++;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>break;</STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>// break is mandatory; no fall-through</em><BR>&nbsp;&nbsp;<STRONG>case</STRONG> "blue":&nbsp;&nbsp; b++;&nbsp;&nbsp; <STRONG>break;</STRONG> <BR>&nbsp;&nbsp;<STRONG>case</STRONG> "green": g++;&nbsp;&nbsp; <STRONG>break;</STRONG> <BR>&nbsp;&nbsp;<STRONG>default:</STRONG> other++;&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>break;</STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>// break necessary on default</em><BR>} </p></TD></TR><TR><TD colSpan="2"><TABLE id="Table7" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Loops</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="259"><p><STRONG>while</STRONG> (i &lt; 10) <BR>&nbsp;&nbsp;i++;<BR><BR><STRONG>for</STRONG> (i = 2; i &lt;= 10; i += 2) <BR>&nbsp;&nbsp;System.out.println(i);</p><p><STRONG>do</STRONG> <BR>&nbsp;&nbsp;i++; <BR><STRONG>while</STRONG> (i &lt; 10);</p><p><strong>for</strong> (int i <strong>:</strong> numArray)&nbsp;&nbsp;// foreach construct&nbsp;&nbsp;<BR>&nbsp;&nbsp;sum += i;</p><p>// for loop can be used to iterate through any Collection<BR>import java.util.ArrayList;<BR>ArrayList&lt;Object&gt; list = new ArrayList&lt;Object&gt;();<BR>list.add(10);&nbsp;&nbsp;&nbsp;&nbsp;// boxing converts to instance of Integer<BR>list.add("Bisons");<BR>list.add(2.3);&nbsp;&nbsp;&nbsp;&nbsp;// boxing converts to instance of Double<BR><BR><strong>for</strong> (Object o <strong>:</strong> list)<BR>&nbsp;&nbsp;System.out.println(o); </p></TD><TD vAlign="top" height="259"><p><STRONG>while</STRONG> (i &lt; 10) <BR>&nbsp;&nbsp;i++;<BR><BR><STRONG>for</STRONG> (i = 2; i &lt;= 10; i += 2) <BR>&nbsp;&nbsp;Console.WriteLine(i);</p><p><STRONG>do</STRONG> <BR>&nbsp;&nbsp;i++; <BR><STRONG>while</STRONG> (i &lt; 10);</p><p><STRONG>foreach</STRONG> (int i <STRONG>in</STRONG> numArray)&nbsp;&nbsp;<BR>&nbsp;&nbsp;sum += i;</p><p><em>// foreach can be used to iterate through any collection</em> <BR>using System.Collections;<BR>ArrayList list = new ArrayList();<BR>list.Add(10);<BR>list.Add("Bisons");<BR>list.Add(2.3);<BR><BR><STRONG>foreach</STRONG> (Object o <STRONG>in</STRONG> list)<BR>&nbsp;&nbsp;Console.WriteLine(o);</p></TD></TR><TR><TD colSpan="2"><TABLE id="Table8" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Arrays</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="144">int nums<STRONG>[]</STRONG> = {1, 2, 3};&nbsp;&nbsp; <em>or</em>&nbsp;&nbsp; int<STRONG>[]</STRONG> nums = {1, 2, 3};<BR>for (int i = 0; i &lt; nums.length; i++)<BR>&nbsp;&nbsp;System.out.println(nums[i]);<BR><BR>String names[] = new String[5];<BR>names[0] = "David";<BR><BR>float twoD<STRONG>[][]</STRONG> = new float[rows][cols];<BR>twoD[2][0] = 4.5;<p>int<STRONG>[][]</STRONG> jagged = new int[5][]; <BR>jagged[0] = new int[5]; <BR>jagged[1] = new int[2]; <BR>jagged[2] = new int[3]; <BR>jagged[0][4] = 5; </p></TD><TD height="144">int<STRONG>[]</STRONG> nums = {1, 2, 3};<BR>for (int i = 0; i &lt; nums.Length; i++)<BR>&nbsp;&nbsp;Console.WriteLine(nums[i]);<BR><BR>string[] names = new string[5];<BR>names[0] = "David";<BR><BR>float<STRONG>[,]</STRONG> twoD = new float[rows, cols];<BR>twoD[2,0] = 4.5f;<p>int<STRONG>[][]</STRONG> jagged = new int[3][] {<BR>&nbsp;&nbsp;&nbsp;&nbsp;new int[5], new int[2], new int[3] }; <BR>jagged[0][4] = 5; </p></TD></TR><TR><TD colSpan="2"><TABLE id="Table9" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Functions</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD><TR vAlign="top"><TD width="50%"><TABLE cellPadding="0" width="100%" border="0"><TBODY><TR vAlign="top"><TD width="50%">// Return single value<BR><STRONG>int</STRONG> Add(int x, int y) { <BR>&nbsp;&nbsp; <STRONG>return</STRONG> x + y; <BR>}<p>int sum = Add(2, 3); </p></TD><TD width="50%">// Return no value<BR><STRONG>void</STRONG> PrintSum(int x, int y) { <BR>&nbsp;&nbsp; System.out.println(x + y); <BR>}<p>PrintSum(2, 3); </p></TD></TR></TBODY></TABLE><p>// Primitive types and references are always passed by value<BR>void TestFunc(int x, Point p) {<BR>&nbsp;&nbsp; x++; <BR>&nbsp;&nbsp; p.x++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Modifying property of the object<BR>&nbsp;&nbsp; p = null;&nbsp;&nbsp;&nbsp;&nbsp;// Remove local reference to object <BR>} </p><p>class Point { <BR>&nbsp;&nbsp; public int x, y; <BR>}</p><p>Point p = new Point(); <BR>p.x = 2; <BR>int a = 1; <BR>TestFunc(a, p);<BR>System.out.println(a + " " + p.x + " " + (p == null) );&nbsp;&nbsp;// 1 3 false <BR><BR><BR><BR><BR><p>// Accept variable number of arguments<BR>int Sum(int <STRONG>...</STRONG> nums) {<BR>&nbsp;&nbsp;int sum = 0;<BR>&nbsp;&nbsp;for (int i : nums)<BR>&nbsp;&nbsp;&nbsp;&nbsp;sum += i;<BR>&nbsp;&nbsp;return sum;<BR>} </p><p>int total = Sum(4, 3, 2, 1);&nbsp;&nbsp; // returns 10</p></TD><TD width="50%"><TABLE id="Table1" cellPadding="0" width="100%" border="0"><TBODY><TR vAlign="top"><TD width="50%">// Return single value<BR><STRONG>int</STRONG> Add(int x, int y) { <BR>&nbsp;&nbsp; <STRONG>return</STRONG> x + y; <BR>}<p>int sum = Add(2, 3); </p></TD><TD width="50%">// Return no value<BR><STRONG>void</STRONG> PrintSum(int x, int y) { <BR>&nbsp;&nbsp; Console.WriteLine(x + y); <BR>}<p>PrintSum(2, 3); </p></TD></TR></TBODY></TABLE><p>// Pass by value (default), in/out-reference (ref), and out-reference (out) <BR>void TestFunc(int x, <STRONG>ref</STRONG> int y, <STRONG>out</STRONG> int z, Point p1, <STRONG>ref</STRONG> Point p2) { <BR>&nbsp;&nbsp; x++;&nbsp;&nbsp;y++;&nbsp;&nbsp;z = 5; <BR>&nbsp;&nbsp; p1.x++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Modifying property of the object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp; p1 = null;&nbsp;&nbsp;&nbsp;&nbsp;// Remove local reference to object <BR>&nbsp;&nbsp; p2 = null;&nbsp;&nbsp; // Free the object <BR>}</p><p>class Point { <BR>&nbsp;&nbsp; public int x, y; <BR>}</p><p>Point p1 = new Point(); <BR>Point p2 = new Point(); <BR>p1.x = 2; <BR>int a = 1, b = 1, c;&nbsp;&nbsp; // Output param doesn't need initializing <BR>TestFunc(a, <STRONG>ref</STRONG> b, <STRONG>out</STRONG> c, p1, <STRONG>ref</STRONG> p2); <BR>Console.WriteLine("{0} {1} {2} {3} {4}", <BR>&nbsp;&nbsp; a, b, c, p1.x, p2 == null);&nbsp;&nbsp; // 1 2 5 3 True</p><p>// Accept variable number of arguments<BR>int Sum(<STRONG>params</STRONG> int[] nums) {<BR>&nbsp;&nbsp;int sum = 0;<BR>&nbsp;&nbsp;foreach (int i in nums)<BR>&nbsp;&nbsp;&nbsp;&nbsp;sum += i;<BR>&nbsp;&nbsp;return sum;<BR>}</p><p>int total = Sum(4, 3, 2, 1);&nbsp;&nbsp; <em>// returns 10</em></p></TD></TR><TR><TD colSpan="2"><TABLE id="Table10" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Strings</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD><p>// String concatenation<BR><STRONG>String</STRONG> school = "Harding "; <BR>school = school + "University";&nbsp;&nbsp; // school is "Harding University"</p><p>// String comparison<BR>String mascot = "Bisons"; <BR>if (mascot == "Bisons")&nbsp;&nbsp;&nbsp;&nbsp;// Not the correct way to do string comparisons<BR>if (mascot.<STRONG>equals</STRONG>("Bisons"))&nbsp;&nbsp; // true<BR>if (mascot.<STRONG>equalsIgnoreCase</STRONG>("BISONS"))&nbsp;&nbsp; // true<BR>if (mascot.<STRONG>compareTo</STRONG>("Bisons") == 0)&nbsp;&nbsp; // true</p><p>System.out.println(mascot.<STRONG>substring</STRONG>(2, 5));&nbsp;&nbsp; // Prints "son"</p><p>// My birthday: Oct 12, 1973<BR>java.util.Calendar c = new java.util.GregorianCalendar(1973, 10, 12);<BR>String s = String.format("My birthday: %1$tb %1$te, %1$tY", c);</p><p>// Mutable string <BR><STRONG>StringBuffer</STRONG> buffer = new <STRONG>StringBuffer</STRONG>("two "); <BR>buffer.<STRONG>append</STRONG>("three "); <BR>buffer.<STRONG>insert</STRONG>(0, "one "); <BR>buffer.<STRONG>replace</STRONG>(4, 7, "TWO"); <BR>System.out.println(buffer);&nbsp;&nbsp;&nbsp;&nbsp; // Prints "one TWO three"</p></TD><TD><p>// String concatenation<BR><STRONG>string</STRONG> school = "Harding "; <BR>school = school + "University";&nbsp;&nbsp; // school is "Harding University"</p><p>// String comparison<BR>string mascot = "Bisons"; <BR>if (mascot == "Bisons")&nbsp;&nbsp;&nbsp;&nbsp;// true<BR>if (mascot.<STRONG>Equals</STRONG>("Bisons"))&nbsp;&nbsp; // true<BR>if (mascot.<STRONG>ToUpper</STRONG>().<STRONG>Equals</STRONG>("BISONS"))&nbsp;&nbsp; // true<BR>if (mascot.<STRONG>CompareTo</STRONG>("Bisons") == 0)&nbsp;&nbsp;&nbsp;&nbsp;// true</p><p>Console.WriteLine(mascot.<STRONG>Substring</STRONG>(2, 3));&nbsp;&nbsp;&nbsp;&nbsp;// Prints "son"</p><p>// My birthday: Oct 12, 1973<BR>DateTime dt = new DateTime(1973, 10, 12);<BR>string s = "My birthday: " + dt.ToString("MMM dd, yyyy"); </p><p>// Mutable string <BR>System.Text.<STRONG>StringBuilder</STRONG> buffer = new System.Text.<STRONG>StringBuilder</STRONG>("two "); <BR>buffer.<STRONG>Append</STRONG>("three "); <BR>buffer.<STRONG>Insert</STRONG>(0, "one "); <BR>buffer.<STRONG>Replace</STRONG>("two", "TWO"); <BR>Console.WriteLine(buffer);&nbsp;&nbsp;&nbsp;&nbsp; // Prints "one TWO three"</p></TD></TR><TR><TD colSpan="2"><TABLE id="Table11" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Exception Handling</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="96"><p>// Must be in a method that is declared to throw this exception<BR>Exception ex = new Exception("Something is really wrong."); <BR><STRONG>throw</STRONG> ex;&nbsp;&nbsp;</p><p><STRONG>try</STRONG> {<BR>&nbsp;&nbsp;y = 0; <BR>&nbsp;&nbsp;x = 10 / y;<BR>} <STRONG>catch</STRONG> (Exception ex) {<BR>&nbsp;&nbsp;System.out.println(ex.getMessage()); <BR>} <STRONG>finally</STRONG> {<BR>&nbsp;&nbsp;// Code that always gets executed<BR>} </p></TD><TD><p>Exception up = new Exception("Something is really wrong."); <BR><STRONG>throw</STRONG> up;&nbsp;&nbsp;// ha ha </p><p><STRONG><BR>try</STRONG> {<BR>&nbsp;&nbsp;y = 0; <BR>&nbsp;&nbsp;x = 10 / y;<BR>} <STRONG>catch</STRONG> (Exception ex) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Variable "ex" is optional<BR>&nbsp;&nbsp;Console.WriteLine(ex.Message); <BR>} <STRONG>finally</STRONG> {<BR>&nbsp;&nbsp;// Code that always gets executed<BR>} </p></TD></TR><TR><TD colSpan="2"><TABLE id="Table12" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Namespaces</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="163"><p><STRONG>package</STRONG> harding.compsci.graphics; </p><p><STRONG><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>import</STRONG> harding.compsci.graphics.Rectangle;&nbsp;&nbsp;// Import single class </p><p><STRONG>import</STRONG> harding.compsci.graphics.*;&nbsp;&nbsp; // Import all classes </p></TD><TD height="163"><p><STRONG>namespace</STRONG> Harding.Compsci.Graphics {<BR>&nbsp;&nbsp;...<BR>} </p><p>or </p><p><STRONG>namespace</STRONG> Harding {<BR>&nbsp;&nbsp;<STRONG>namespace</STRONG> Compsci {<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>namespace</STRONG> Graphics {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR>} </p><p>// Import all class. Can't import single class.<BR><STRONG>using</STRONG> Harding.Compsci.Graphics; </p></TD></TR><TR><TD colSpan="2"><TABLE id="Table13" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Classes / Interfaces</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD><p>Accessibility keywords <BR>public<BR>private<BR>protected<BR>static</p><BR><BR><p>// Inheritance<BR><STRONG>class</STRONG> FootballGame <STRONG>extends</STRONG> Competition {<BR>&nbsp;&nbsp;...<BR>} </p><p>// Interface definition<BR><STRONG>interface</STRONG> IAlarmClock {<BR>&nbsp;&nbsp;...<BR>} </p><p>// Extending an interface <BR><STRONG>interface</STRONG> IAlarmClock <STRONG>extends</STRONG> IClock {<BR>&nbsp;&nbsp;...<BR>} </p><p>// Interface implementation<BR><STRONG>class</STRONG> WristWatch <STRONG>implements</STRONG> IAlarmClock, ITimer {<BR>&nbsp;&nbsp; ...<BR>} </p></TD><TD><p>Accessibility keywords <BR>public<BR>private<BR>internal<BR>protected<BR>protected internal<BR>static</p><p>// Inheritance<BR><STRONG>class</STRONG> FootballGame <STRONG>:</STRONG> Competition {<BR>&nbsp;&nbsp;...<BR>} </p><p>// Interface definition<BR><STRONG>interface</STRONG> IAlarmClock {<BR>&nbsp;&nbsp;...<BR>} </p><p>// Extending an interface <BR><STRONG>interface</STRONG> IAlarmClock : IClock {<BR>&nbsp;&nbsp;...<BR>} </p><p>// Interface implementation<BR><STRONG>class</STRONG> WristWatch <STRONG>:</STRONG> IAlarmClock, ITimer {<BR>&nbsp;&nbsp; ...<BR>} </p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table14" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Constructors / Destructors</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="176"><p>class SuperHero { <BR>&nbsp;&nbsp;private int mPowerLevel; </p><p>&nbsp;&nbsp;public SuperHero() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;mPowerLevel = 0; <BR>&nbsp;&nbsp;} </p><p>&nbsp;&nbsp;public SuperHero(int powerLevel) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;this.mPowerLevel= powerLevel; <BR>&nbsp;&nbsp;}</p><p>&nbsp;&nbsp;// No destructors, just override the finalize method<BR>&nbsp;&nbsp;protected void <STRONG>finalize</STRONG>() throws Throwable { <BR>&nbsp;&nbsp;&nbsp;&nbsp;super.finalize();&nbsp;&nbsp; // Always call parent's finalizer&nbsp;&nbsp; <BR>&nbsp;&nbsp;}<BR>}</p></TD><TD height="176"><p>class SuperHero {<BR>&nbsp;&nbsp;private int mPowerLevel;<BR><BR>&nbsp;&nbsp;public SuperHero() {<BR>&nbsp;&nbsp;&nbsp;&nbsp; mPowerLevel = 0;<BR>&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;public SuperHero(int powerLevel) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;this.mPowerLevel= powerLevel; <BR>&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;<STRONG>~</STRONG>SuperHero() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;// Destructor code to free unmanaged resources.<BR>&nbsp;&nbsp;&nbsp;&nbsp;// Implicitly creates a Finalize method.<BR>&nbsp;&nbsp;}<BR>}</p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table15" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Objects</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="163"><p>SuperHero hero = new SuperHero(); </p><p>hero.setName("SpamMan"); <BR>hero.setPowerLevel(3); <BR><BR>hero.Defend("Laura Jones");<BR>SuperHero.Rest();&nbsp;&nbsp;// Calling static method</p><p>SuperHero hero2 = hero;&nbsp;&nbsp; // Both refer to same object <BR>hero2.setName("WormWoman"); <BR>System.out.println(hero.getName());&nbsp;&nbsp;// Prints WormWoman <BR><BR>hero = <STRONG>null</STRONG>;&nbsp;&nbsp; // Free the object </p><p>if (hero == <STRONG>null</STRONG>)<BR>&nbsp;&nbsp;hero = new SuperHero();</p><p>Object obj = new SuperHero(); <BR>System.out.println("object's type: " + obj.<STRONG>getClass()</STRONG>.toString()); <BR>if (obj <STRONG>instanceof</STRONG> SuperHero) <BR>&nbsp;&nbsp;System.out.println("Is a SuperHero object.");</p></TD><TD height="163"><p>SuperHero hero = new SuperHero(); <BR><BR>hero.Name = "SpamMan"; <BR>hero.PowerLevel = 3;</p><p>hero.Defend("Laura Jones");<BR>SuperHero.Rest();&nbsp;&nbsp; // Calling static method</p><p>SuperHero hero2 = hero;&nbsp;&nbsp; // Both refer to same object <BR>hero2.Name = "WormWoman"; <BR>Console.WriteLine(hero.Name);&nbsp;&nbsp; // Prints WormWoman</p><p>hero = <STRONG>null</STRONG> ;&nbsp;&nbsp; // Free the object </p><p>if (hero == <STRONG>null</STRONG>)<BR>&nbsp;&nbsp;hero = new SuperHero();</p><p>Object obj = new SuperHero(); <BR>Console.WriteLine("object's type: " + obj.<STRONG>GetType()</STRONG>.ToString()); <BR>if (obj <STRONG>is</STRONG> SuperHero) <BR>&nbsp;&nbsp;Console.WriteLine("Is a SuperHero object.");</p></TD></TR><TR><TD colSpan="2"><TABLE id="Table16" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Properties</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD><TR vAlign="top"><TD width="50%" height="134"><p>private int mSize;</p><p>public int <STRONG>getSize</STRONG>() { return mSize; } <BR>public void <STRONG>setSize</STRONG>(int value) {<BR>&nbsp;&nbsp;if (value &lt; 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;mSize = 0; <BR>&nbsp;&nbsp;else <BR>&nbsp;&nbsp;&nbsp;&nbsp;mSize = value; <BR>} </p><p><BR>int s = shoe.getSize();<BR>shoe.setSize(s+1);</p></TD><TD width="50%" height="134"><p>private int mSize;</p><p>public int Size { <BR>&nbsp;&nbsp;<STRONG>get</STRONG> { return mSize; } <BR>&nbsp;&nbsp;<STRONG>set</STRONG> { <BR>&nbsp;&nbsp;&nbsp;&nbsp;if (value &lt; 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mSize = 0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;else <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mSize = value; <BR>&nbsp;&nbsp;} <BR>} </p><p>shoe.Size++; </p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table17" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Structs</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD height="256"><em><BR><BR></em><p> </p><p><em>No structs in Java.</em></p></TD><TD height="256"><STRONG>struct</STRONG> StudentRecord {<BR>&nbsp;&nbsp;public string name;<BR>&nbsp;&nbsp;public float gpa;<BR><BR>&nbsp;&nbsp;public StudentRecord(string name, float gpa) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;this.name = name;<BR>&nbsp;&nbsp;&nbsp;&nbsp;this.gpa = gpa;<BR>&nbsp;&nbsp;}<BR>}<BR><BR>StudentRecord stu = new StudentRecord("Bob", 3.5f);<BR>StudentRecord stu2 = stu;&nbsp;&nbsp;<BR><BR>stu2.name = "Sue";<BR>Console.WriteLine(stu.name);&nbsp;&nbsp;&nbsp;&nbsp;// Prints "Bob"<BR>Console.WriteLine(stu2.name);&nbsp;&nbsp; // Prints "Sue"</TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table18" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">Console I/O</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD width="50%" height="163">java.io.DataInput in = new java.io.DataInputStream(System.in);<BR>System.out.print("What is your name? ");<BR>String name = in.readLine();<BR>System.out.print("How old are you? ");<BR>int age = Integer.parseInt(in.readLine());<BR>System.out.println(name + " is " + age + " years old.");<p><BR>int c = System.in.read();&nbsp;&nbsp; // Read single char<BR>System.out.println(c);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Prints 65 if user enters "A"</p><p>// The studio costs $499.00 for 3 months.<BR>System.out.printf("The %s costs $%.2f for %d months.%n", "studio", 499.0, 3);</p><p>// Today is 06/25/04<BR>System.out.printf("Today is %tD&#92;n", new java.util.Date());</p></TD><TD width="50%" height="163">Console.Write("What's your name? ");<BR>string name = Console.ReadLine();<BR>Console.Write("How old are you? ");<BR>int age = Convert.ToInt32(Console.ReadLine());<BR>Console.WriteLine("{0} is {1} years old.", name, age);<BR>// or<BR>Console.WriteLine(name + " is " + age + " years old.");<p>int c = Console.Read();&nbsp;&nbsp;// Read single char<BR>Console.WriteLine(c);&nbsp;&nbsp;&nbsp;&nbsp;// Prints 65 if user enters "A"</p><p>// The studio costs $499.00 for 3 months.<BR>Console.WriteLine("The {0} costs {1:C} for {2} months.&#92;n", "studio", 499.0, 3);</p><p>// Today is 06/25/2004<BR>Console.WriteLine("Today is " + DateTime.Now.ToShortDateString()); </p></TD></TR><TR align="middle"><TD colSpan="2"><TABLE id="Table19" width="100%" border="0"><TBODY><TR align="middle"><TD width="20%">Java</TD><TD width="60%">File I/O</TD><TD width="20%">C#</TD></TR></TBODY></TABLE></TD></TR><TR vAlign="top"><TD width="50%" height="163"><p>import java.io.*;</p><p>// Character stream writing<BR><STRONG>FileWriter</STRONG> writer = new FileWriter("c:&#92;&#92;myfile.txt");<BR>writer.write("Out to file.&#92;n");<BR>writer.close();</p><p>// Character stream reading<BR><STRONG>FileReader</STRONG> reader = new FileReader("c:&#92;&#92;myfile.txt");<BR><STRONG>BufferedReader</STRONG> br = new BufferedReader(reader);<BR>String line = br.readLine(); <BR>while (line != null) {<BR>&nbsp;&nbsp;System.out.println(line); <BR>&nbsp;&nbsp;line = br.readLine(); <BR>} <BR>reader.close(); </p><p>// Binary stream writing<BR><STRONG>FileOutputStream</STRONG> out = new FileOutputStream("c:&#92;&#92;myfile.dat");<BR>out.write("Text data".getBytes());<BR>out.write(123);<BR>out.close();</p><p>// Binary stream reading<BR><STRONG>FileInputStream</STRONG> in = new FileInputStream("c:&#92;&#92;myfile.dat");<BR>byte buff[] = new byte[9];<BR>in.read(buff, 0, 9);&nbsp;&nbsp; // Read first 9 bytes into buff<BR>String s = new String(buff);<BR>int num = in.read();&nbsp;&nbsp; // Next is 123<BR>in.close();</p></TD><TD width="50%" height="163"><p>using System.IO;</p><p>// Character stream writing<BR><STRONG>StreamWriter</STRONG> writer = File.CreateText("c:&#92;&#92;myfile.txt"); <BR>writer.WriteLine("Out to file."); <BR>writer.Close(); </p><p>// Character stream reading<BR><STRONG>StreamReader</STRONG> reader = File.OpenText("c:&#92;&#92;myfile.txt"); <BR>string line = reader.ReadLine(); <BR>while (line != null) {<BR>&nbsp;&nbsp;Console.WriteLine(line); <BR>&nbsp;&nbsp;line = reader.ReadLine(); <BR>} <BR>reader.Close(); </p><p><BR>// Binary stream writing<BR><STRONG>BinaryWriter</STRONG> out = new BinaryWriter(File.OpenWrite("c:&#92;&#92;myfile.dat")); <BR>out.Write("Text data"); <BR>out.Write(123); <BR>out.Close(); </p><p>// Binary stream reading<BR><STRONG>BinaryReader</STRONG> in = new BinaryReader(File.OpenRead("c:&#92;&#92;myfile.dat")); <BR>string s = in.ReadString(); <BR>int num = in.ReadInt32(); <BR>in.Close();</p></TD></TR></table><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7883/</link>
<title><![CDATA[Flex与.NET互操作（十四）：FluorineFx + Flex视频聊天室案例开发]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Sun, 09 Aug 2009 07:36:36 +0000</pubDate> 
<guid>http://www.niuc.net/post/7883/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本文将使用FluorineFx和Flex结合介绍一个简单的视频聊天室案例开发，希望通过此篇和大家交流FluorineFx和Flex的相关技术，同时也希望本篇可以帮助到需要使用FluorineFx做及时应用开发的新手朋友。首先列举下本篇中所涉及到的开发环境和相关技术以及简单的需求定义：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Microsoft Visual Studio 2008(VS SP1)+.NET Framework 3.5(SP1)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. FluorineFx v1.0.0.15 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Adobe Flex Builder 3 + Flex SDK 3.2<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Microsoft Office Access 2003<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. ADO.NET , Linq.....<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本篇的案例的功能需求定义如下：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 用户注册/登录聊天室<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 成功登录聊天室后通过选择在线用户进行视频连接完成视频和文字聊天（一对一私聊）<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 提供小喇叭功能，实现全服务器发送消息（一对多，一人发送全聊天室的用户都可见）<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. 提供聊天表情选择窗口，实现聊天表情的发送。<br/><br/><strong>1、服务器端开发</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本篇主要介绍了使用FluorineFx所提供的ApplicationAdapter来建立自己的及时通信应用Adapter，提供及时通信、实况流服务，以及通过远程共享对象管理在线用户列表的功能。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在我之前的一篇文章里曾经介绍过FluorineFx的ApplicationAdapter的基本步骤，以及使用FluorineFx的ApplicationAdapter来开发及时通信应用的相关知识点。ApplicationAdapter应用最终需要部署到支持FluorineFx服务的Web应用(ASP.NET网站)上，如下图则表示了FluorineFx应用的目录结构。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于使用过FluorineFx开发应用的朋友来说，这个图在熟悉不过了。要使用FluorineFx开发及时通信应用，项目结构就必须这样搭建，首先看看本篇案例的解决方案截图：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=257" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=257" target="_blank">http://www.niuc.net/attachment.php?fid=257</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;从上面的解决方案截图可以看到，整个项目由两部分构成，一个是FluorineFx的类库，封装了远程服务(RemotingService)接口和及时通信应用程序（ApplicationAdapter）。另一个则是FluorineFx网站（和ASP.NET网站没多大的区别，不同的是其中加入了FluorineFx的一些相关配置）。<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=258" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=258" target="_blank">http://www.niuc.net/attachment.php?fid=258</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了方便演示案例本篇就直接使用的 Access做为数据库，根据数据库的字段结构建立了一个数据传输对象（DTO），同时为该DTO对象标记<strong>[FluorineFx.TransferObject]</strong>，以使其可以作为FluorineFx的数据传输对象使用。<br/><br/><div class="code">namespace ChatRoom.Services.DTO<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// 用户信息(数据传输对象)<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;FluorineFx.TransferObject&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class UserInfo<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 构造方法<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public UserInfo() { }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public int ID { get; set; }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string UserName { get; set; }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string NickName { get; set; }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Password { get; set; }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string HeadImage { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;远程服务接口（DataService）提供了用户注册，登陆等最基本的通信接口方法，在了解通信接口之前首先学习一个工具类，该类的提供了一个将DataTable类型数据转话为IList&lt;Object&gt;类型返回，详细代码如下：<br/><br/><div class="code">namespace ChatRoom.Services.Utils<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;public static class ConvertUtils<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 提供将DataTable类型对象转换为List集合<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;table&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static List&lt;T&gt; ConvertToList&lt;T&gt;(DataTable table) where T : new()<br/>&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;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;T&gt; list = null;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (table != null)<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;DataColumnCollection columns = table.Columns;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int columnCount = columns.Count;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T type = new T();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type columnType = type.GetType();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyInfo&#91;&#93; properties = columnType.GetProperties();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (properties.Length == columnCount)<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;list = new List&lt;T&gt;();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach (DataRow currentRow in table.Rows)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; columnCount; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int j = 0; j &lt; properties.Length; j++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (columns&#91;i&#93;.ColumnName == properties&#91;j&#93;.Name)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;properties&#91;j&#93;.SetValue(type, currentRow&#91;i&#93;, null);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;list.Add(type);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type = new T();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&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;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<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;list = null;<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;&nbsp;&nbsp;&nbsp;&nbsp;else<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;throw new ArgumentNullException(&quot;参数不能为空&quot;);<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;return list;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是使用FluorineFx提供的远程服务接口的详细定义：<br/><br/><div class="code">namespace ChatRoom.Services<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class DataService<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public DataService()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 用户注册<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;info&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public bool Register(UserInfo info)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info.Password = FormsAuthentication.HashPasswordForStoringInConfigFile(info.Password, &quot;MD5&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder CommandText = new StringBuilder(&quot;insert into UserInfo values (&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CommandText.Append(string.Format(&quot;&#039;{0}&#039;,&#039;{1}&#039;,&#039;{2}&#039;,&#039;{3}&#039;)&quot;, info.UserName, info.Password, info.NickName, info.HeadImage));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try<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;int row = DataBase.ExecuteSQL(CommandText.ToString());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (row &gt; 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<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;catch (Exception ex)<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;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 用户登录<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;info&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public UserInfo Login(UserInfo info)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info.Password = FormsAuthentication.HashPasswordForStoringInConfigFile(info.Password, &quot;MD5&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder CommandText = new StringBuilder(&quot;select * from UserInfo where &quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CommandText.Append(string.Format(&quot;UserName=&#039;{0}&#039; and Password=&#039;{1}&#039;&quot;, info.UserName, info.Password));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try<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;DataTable table = DataBase.ExecuteQuery(CommandText.ToString());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (table != null)<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;return ConvertUtils.ConvertToList&lt;UserInfo&gt;(table)&#91;0&#93;;<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;return null;<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;catch (Exception ex)<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;return null;<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;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FluorineFx.Messaging.Adapter.ApplicationAdapter做为新的应用程序的基类，提供了客户端与应用程序之间通信的接口方法、数据流服务以及共享对象服务等。它能够时时处理应用程序的启动、停止、客户端的连接和断开等及时操作。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在本篇案例项目中，我所建立的ApplicationAdapter为ChatRoomApplication，用来提供启动及时应用服务器，接受客户端连接和断开以及视频流服务等功能。这里需要注意一点，在接受客户端连接的时候业务处理流程，在应用程序启动的时候就将会创建一个共享对象，用来保存在线用户列表。<br/><br/><div class="code">public override bool AppStart(IScope application)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//用户共享对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;CreateSharedObject(application, &quot;OnLineUsers&quot;, false);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return base.AppStart(application);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当用户通过客户端连接服务器的时候，将用户信息传递到服务器，服务器端接受到数据后将会对用户数据进行验证（验证用户名和密码是否匹配），如果验证失败则直接返回false表示连接服务器失败，如果验证通过则设置当前连接的属性并连接到共享对象，然后取出共享对象里的在线用户列表数据，判断当前连接到服务器的用户是否在线，如果用户已在线则返回false表示用户登录失败，并给于提示当前用户已经登录。如果用户没有存在于共享里则表示当前连接的用户没有登录，那么就将当前连接的用户信息写入共享对象，客户端会通过异步事件处理函数接收到最新的在线用户列表数据。 <br/><br/><div class="code">public override bool AppConnect(IConnection connection, object&#91;&#93; parameters)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;UserInfo info = ((Dictionary&lt;string, object&gt;)parameters&#91;0&#93;)&#91;&quot;0&quot;&#93; as UserInfo;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;connection.Client.SetAttribute(&quot;UserName&quot;, info.UserName);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;//连接到共享对<br/>&nbsp;&nbsp;&nbsp;&nbsp;ISharedObject users = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (users == null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CreateSharedObject(connection.Scope, &quot;OnLineUsers&quot;, false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;UserInfo&gt; onLineUserList = users.GetAttribute(&quot;UserInfo&quot;) as List&lt;UserInfo&gt;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (onLineUserList != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;UserInfo&gt; tempList = (from u in onLineUserList<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where u.UserName == info.UserName<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select u<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ).ToList();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (tempList.Count &gt; 0)<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;//Server RPC<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CallClientMethod(connection, &quot;onLogined&quot;, &quot;当前用户已经登录&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<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;else<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;onLineUserList.Add(info);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users.SetAttribute(&quot;UserInfo&quot;, onLineUserList);<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;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onLineUserList = new List&lt;UserInfo&gt; { info };<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users.SetAttribute(&quot;UserInfo&quot;, onLineUserList);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;return base.AppConnect(connection, parameters);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OK，到这里就完成了对用户进行有效验证和接受与拒绝连接的功能，那么如果是用户下线了或是无意之间关闭了浏览器呢？这种情况应当如何去处理，如果不处理的话那么用户是不是会一直卡在线上呢？答案是肯定的。FluorineFx为此也提供了接口来处理用户下线的操作，那么在这里我们需要做什么呢？需要做的就是取出当前退出系统的客户端连接属性值，然后在取出共享对象里的在线用户列表数据，根据用户连接时所设置的属性进行循环判断，找到当前退出系统的用户数据，最后将他从共享对象里删除，服务器端的共享对象一但改变，所有连接到服务器的客户端都会通过共享对象的异步事件得到最新的数据，用来更新客户端的显示列表。<br/><br/><div class="code">public override void AppDisconnect(IConnection connection)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;string userName = connection.Client.GetAttribute(&quot;UserName&quot;) as string;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;ISharedObject users = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (users != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;UserInfo&gt; onLineUserList = users.GetAttribute(&quot;UserInfo&quot;) as List&lt;UserInfo&gt;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (onLineUserList != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;UserInfo&gt; tempList = onLineUserList.FindAll(c =&gt; c.UserName.Length &gt; 0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach (var item in tempList)<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;if (item.UserName.Equals(userName))<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;onLineUserList.Remove(item);<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;&nbsp;&nbsp;&nbsp;&nbsp;users.SetAttribute(&quot;UserInfo&quot;, onLineUserList);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;base.AppDisconnect(connection);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;到这里服务器端的开发就基本完成了，现在就需要将这个ApplicationAdapter配置好，然后启动通过网站启动服务，Flex或者是Flash就可以通过rtmp协议连接了。首先需要配置的是rtmp协议通信信道：<br/><br/><div class="code">&lt;channel-definition id=&quot;my-rtmp&quot; class=&quot;mx.messaging.channels.RTMPChannel&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;endpoint uri=&quot;rtmp://{server.name}:2777&quot; class=&quot;flex.messaging.endpoints.RTMPEndpoint&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;idle-timeout-minutes&gt;20&lt;/idle-timeout-minutes&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;<br/>&lt;/channel-definition&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;然后就是在应用目录下面配置ApplicationAdapter，指定当前这个应用又那一个Adapter来处理。建立app.config文件进行如下配置：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;configuration&gt;<br/>&nbsp;&nbsp;&lt;application-handler type=&quot;ChatRoom.Services.ChatRoomApplication&quot;/&gt;<br/>&lt;/configuration&gt;</div><br/><br/><strong>2、客户端开发</strong><br/><br/>首先就是客户实现用户登录，通过FluorineFx提供的RemotingService的接口方法进行数据验证。<br/><br/><div class="code">private function onLogin(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;remoteConn = new RemotingConnection(&quot;http://localhost:2020/ChatRoom.FluorineFxWeb/Gateway.aspx&quot;,ObjectEncoding.AMF3);<br/>&nbsp;&nbsp;&nbsp;&nbsp;myInfo = new UserInfo();<br/>&nbsp;&nbsp;&nbsp;&nbsp;myInfo.UserName=this.txtUserName.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;myInfo.Password=this.txtPassword.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;remoteConn.RemotingCall(&quot;ChatRoom.Services.DataService.Login&quot;,onLoginResult,onLoginFault,myInfo);<br/>}<br/><br/>private function onLoginResult(result:UserInfo):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(result != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.myInfo = result;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.viewStack.selectedChild = chatView;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rtmpnc = new RtmpConnection(&quot;rtmp://localhost:2777/VideoChat&quot;,ObjectEncoding.AMF3,onNetStatusHandler,myInfo);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.lbState.text = &quot;登陆失败,用户名或密码错误！&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/><br/>private function onLoginFault(event:Object):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.lbState.text = &quot;登陆失败,请重试！&quot;;<br/>}<br/><br/>private function onClear(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.txtUserName.text=&quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.txtPassword.text=&quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.lbState.text=&quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.txtUserName.setFocus();<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RemotingConnection和RtmpConnection是我自己扩展的NetConnection类，功能和NetConnection一样，不同的是封装后的使用相对来说比较方便点。首先通过RemotingService的接口进行用户名和密码验证，通过了则创建一个到RTMP服务器的连接RtmpConnection（等同于NetConnection）。<br/><br/><div class="code">private function onNetStatusHandler(event:NetStatusEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;trace(event.info.code);<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch(event.info.code)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case &quot;NetConnection.Connect.Success&quot;:onConnSuccess();break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case &quot;NetConnection.Connect.Failed&quot;:onConnError();break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/><br/>private function onConnSuccess():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//将自己的视频数据发布到RTMP服务器,这里使用的是FluorineFx<br/>&nbsp;&nbsp;&nbsp;&nbsp;var mic:Microphone = Microphone.getMicrophone();<br/>&nbsp;&nbsp;&nbsp;&nbsp;var publishNs:NetStream = new NetStream(rtmpnc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;publishNs.attachCamera(cam);<br/>&nbsp;&nbsp;&nbsp;&nbsp;publishNs.attachAudio(mic);<br/>&nbsp;&nbsp;&nbsp;&nbsp;publishNs.client = this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;publishNs.publish(myInfo.ID.toString()); //将用户ID作为流名进行发布实况流<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;userSO = SharedObject.getRemote(&quot;OnLineUsers&quot;,rtmpnc.uri,false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;userSO.addEventListener(SyncEvent.SYNC,onSyncHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;userSO.client = this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;userSO.connect(rtmpnc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;timer = new Timer(1000);<br/>&nbsp;&nbsp;&nbsp;&nbsp;timer.addEventListener(TimerEvent.TIMER,onTimerHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;timer.start();<br/>}<br/><br/>private function onConnError():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;trace(&quot;login error&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(&quot;&lt;font color=&#92;&quot;#FF0000&#92;&quot;&gt;系统提示：连接视频服务器失败&lt;/font&gt;&quot;);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;创建连接的同时指定了由那一个方法（onNetStatusHandler）来处理连接状态，通过判断连接状态如果连接成功则将自己的视频数据发布到RTMP服务器（<strong>特别提醒：在发布流的时候是使用的用户ID作为流名，在建立视频聊天的时候需要根据这个ID才能查看到视频</strong>），同时还连接到服务器上的远程共享对象（<strong>作用：通过异步事件处理函数实现在线用户列表</strong>），最后建立了一个Timer是不断的调用服务器方法获取当前系统时间（<strong>注意：实际开发中不建议这样做</strong>）；如果连接服务器失败则在聊天消息显示区输入一条提示信息。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在线用户列表使用共享对象来实现，可以及时的处理用户上线下线功能和实现客户端数据同步更新等。下面是共享对象的异步事件处理函数：<br/><br/><div class="code">private function onSyncHandler(event:SyncEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var array:Array = event.target.data.UserInfo as Array;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(array != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userArray.removeAll();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(var i:Number=0; i&lt;array.length; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var info:UserInfo = array&#91;i&#93; as UserInfo;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userArray.addItem(info);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trace(&quot;userArray length:&quot; + userArray.length);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 从异步事件中取出当前最新的数据，然后添加到用户界面的显示列表数组（userArray）里，Flex直接使用List组件显示在线用户列表，通过绑定userArray设置数据源，当userArray改变后List组件的显示也会同步更新显示。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么怎么去建立视频聊天查看到对方的视频呢？其实实现也很简单，这里还是要从用户列表出发，通过点击用户列表上的在线用户，然后建立与该用户的视频连接。同时判断是否选择的是怎么，本案例中我没有将自己从在线列表里屏蔽而是通过判断当前选择的是否为自己，如果是自己则不进行视频连接，也不能发送文本聊天信息。<br/><br/><div class="code">private function onUserItemHandler(event:Event):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;info = List(event.target).selectedItem as UserInfo;&nbsp;&nbsp;//把当前选择的用户信息通过变量保存下来<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.lbNickName.text = info.NickName;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(info.UserName == myInfo.UserName)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(&quot;&lt;font color=&#92;&quot;#FF0000&#92;&quot;&gt;系统提示：不能和自己进行视频聊天&lt;/font&gt;&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//建立视频流的连接<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(this.ns)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.ns.close();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.ns = new NetStream(this.rtmpnc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.client = this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sound = this.ns.soundTransform;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var v1:Video = new Video();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1.width = 320;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1.height = 240;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1.attachNetStream(ns);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.videoDisplay.addChild(v1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.play(info.ID.toString());&nbsp;&nbsp;//当前选择的用户的ID<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OK，到这里就成功的完成了用户登录，建立与RTMP服务器的连接，发布视频流，接收指定的视频流等功能，接下来就是实现文字聊天的功能了。这里我使用的是第二篇文章里所介绍的方法（<br/><strong>提示：该方法就是直接使用SharedObject的send()方法</strong>）来实现文字聊天功能。<br/><br/><div class="code">private function onSendMessage(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(info!=null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userSO.send(&quot;chatMessage&quot;, this.txtMessage.text, myInfo, info);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.txtMessage.text=&quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(&quot;系统提示：请选择聊天对象&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/><br/>public function chatMessage(message:String, sayUser:UserInfo, recUser:UserInfo):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(recUser.UserName==this.myInfo.UserName)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = sayUser.NickName + &quot;对你说：&quot;+message;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(message);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(sayUser.UserName==this.myInfo.UserName)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = &quot;我对&quot;+recUser.NickName + &quot;说：&quot;+message;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(message);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/><br/>private function writeMessage(message:String):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.txtDisMessage.htmlText += message + &quot;&#92;n&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.txtDisMessage.verticalScrollPosition = this.txtDisMessage.maxVerticalScrollPosition;<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OK，大功告成，现在是集视频和文字聊天的多人在线聊天室就实现了，不足的是只能一对一聊天。如果我要对大家说话怎么办呢？于是我在本案例中设计了一个小喇叭功能，通过发送小喇叭实现全服务器喊话。下边是下喇叭组件代码：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:TitleWindow xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot; width=&quot;540&quot; height=&quot;50&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;headerHeight=&quot;8&quot; roundedBottomCorners=&quot;true&quot; borderColor=&quot;#000000&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;2&quot; y=&quot;3&quot; width=&quot;400&quot; id=&quot;txtMessage&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;466&quot; y=&quot;3&quot; label=&quot;关闭&quot; click=&quot;onClose(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;410&quot; y=&quot;3&quot; label=&quot;发送&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enabled=&quot;{txtMessage.text.length &gt; 0 ? true : false}&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;click=&quot;onSend(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.core.Application;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.events.CloseEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.managers.PopUpManager;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function init():void<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;this.txtMessage.setFocus();<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onClose(event:MouseEvent):void<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;onCloseHandler(null);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onCloseHandler(event:CloseEvent):void<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;Application.application.speakFlag = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PopUpManager.removePopUp(this);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onSend(event:MouseEvent):void<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;Application.application.userSO.send(&quot;speakMessage&quot;,txtMessage.text,Application.application.myInfo);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.txtMessage.text = &quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onCloseHandler(null);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&lt;/mx:TitleWindow&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;同样通过远程共享对象的send()方法实现发送小喇叭功能，在客户端定义一个方法(speakMessage)来接受小喇叭发送的消息内容，然后显示在用户聊天界面上。<br/><br/><div class="code">public var speakFlag:Boolean = false;<br/>private function onSpeaker(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(!speakFlag)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var dis:Speaker = new Speaker();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dis.x = 230;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dis.y = 505;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PopUpManager.addPopUp(dis,this,false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;speakFlag = true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/>public function speakMessage(message:String,info:UserInfo):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;message = &quot;【小喇叭】：&quot; + info.NickName + &quot;说：&quot; + message;<br/>&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(message); <br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;貌似这一整篇都是代码，除了代码我也不知道该怎么去介绍更容易说得清楚了，下面来看看上面的劳动成功，启动服务器后运行多个客户端来聊天测试看看。<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=259" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=259" target="_blank">http://www.niuc.net/attachment.php?fid=259</a><br/><br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=260" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=260" target="_blank">http://www.niuc.net/attachment.php?fid=260</a><br/><br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=261" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=261" target="_blank">http://www.niuc.net/attachment.php?fid=261</a><br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在还差一个重要的功能没有实现了，前面提到过画中画功能，也就是说在和在线朋友进行视频聊天的同时，需要将自己的视频以小视频窗口的方式显示在聊天窗口，实现所谓的画中画功能，显示自己的视频通过初始化方法，程序启动后就直接显示出自己的视频。<br/><br/><div class="code">private function init():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//将自己的视频显示在画中画中<br/>&nbsp;&nbsp;&nbsp;&nbsp;cam = Camera.getCamera();<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(cam != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.myVD.attachCamera(cam);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeMessage(&quot;未能找到视频设备,请检测是否正确安装设备！&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本文就介绍到这里，关于聊天表情的实现这里就不作介绍了，由于时间关系本案例里也没有实现这个功能，有兴趣的朋友可以下载源代码自己去扩展实现聊天表情这个功能。这里我将实现的原理简单说一下，通过TileList组件加载表情图片或动画信息显示出来。<br/><br/><strong>3、应用程序部署</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先需要需要注意一点就是Flex的配置文件<strong>service-config.xml</strong>，后面的flash将通过<strong>service-config.xml</strong>里配置的RTMP通信信道与FluorineFx的RTMP服务器连接连接，详细配置如下： <br/><br/><div class="code">&lt;channel-definition id=&quot;my-rtmp&quot; class=&quot;mx.messaging.channels.RTMPChannel&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;endpoint uri=&quot;rtmp://{server.name}:2777&quot; class=&quot;flex.messaging.endpoints.RTMPEndpoint&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;idle-timeout-minutes&gt;20&lt;/idle-timeout-minutes&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;<br/>&lt;/channel-definition&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 在网站中添件一新Web页面(FluorineChatRoom.aspx)来承载flash（.swf）的运行，将新发布的.swf负载到该页面。<br/><br/><div class="code">&lt;object classid=&quot;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id=&quot;VideoChat&quot; width=&quot;520&quot; height=&quot;520&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;codebase=&quot;http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=&quot;movie&quot; value=&quot;flash/VideoChat.swf&quot; /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=&quot;quality&quot; value=&quot;high&quot; /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=&quot;bgcolor&quot; value=&quot;#869ca7&quot; /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;sameDomain&quot; /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;embed src=&quot;flash/VideoChat.swf&quot; quality=&quot;high&quot; bgcolor=&quot;#869ca7&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width=&quot;520&quot; height=&quot;520&quot; name=&quot;VideoChat&quot; align=&quot;middle&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;play=&quot;true&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop=&quot;false&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quality=&quot;high&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allowScriptAccess=&quot;sameDomain&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type=&quot;application/x-shockwave-flash&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pluginspage=&quot;http://www.adobe.com/go/getflashplayer&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/embed&gt;<br/>&lt;/object&gt;</div><br/><br/><strong>小提示：另外也建议使用swfobject.js来加载swf！</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;然后将宿主FluorineFx提供的RemotingService和ApplicationAdapter的网站发布出来部署到IIS上。<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=262" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=262" target="_blank">http://www.niuc.net/attachment.php?fid=262</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;部署过程中我单独分配了一个Web端口88，OK，现在运行Geteway.aspx就会得到一个地址：http://localhost:88/Gateway.aspx 这个地址就是flash中需要用来作为RPC通信的通信网关地址，简单的理解就是通过这个地址来访问FluorineFx提供的远程服务（RemotingService）。现在回到客户端开发代码中去，修改通信网关的地址，将原来在VS下调试的地址修改为部署到IIS后的访问地址：<br/><br/><div class="code">remoteConn = new RemotingConnection(&quot;http://localhost:2020/ChatRoom.FluorineFxWeb/Gateway.aspx&quot;,ObjectEncoding.AMF3);</div><br/><br/>修改为如下：<br/><br/><div class="code">remoteConn = new RemotingConnection(&quot;http://localhost:88/Gateway.aspx&quot;,ObjectEncoding.AMF3);</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在重新发布flash，将新发布的.swf复制到IIS中部署的站点对应的目录下，到这里在本地测试基本就完成了。但是这样做只能做到本地单机访问，如果要在局域网内访问则需要在IIS中为该应用站点分配IP，然后通过IP访问就OK了。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;服务器主机上又怎么部署呢？通过上面这些步骤或许已经体会到，Flash客户端需要的只是两个地址，一个Gateway.aspx网关地址，一个是RTMP服务器访问地址，其实随便你将这个Web应用这么部署，只要保证这两个地址有效就行了。比如你的服务器IP是：61.128.128.68，在此服务器上部署了FluorineFx网站（绑定的域名为www.mydomain.com）；那么客户端访问RemotingService的地址则为：&quot;http://www.mydomain.com/Gateway.aspx &quot;,RTMP服务器的连地址则为：&quot;rtmp://61.128.128.68:2777/VideoChat&quot;。通过这两地址修改flash端然后重新发布一个.swf覆盖以前的flash文件，这样就可以通过域名在公网上使用本篇所介绍的视频聊天室案例项目了。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本案例并不完善，还有许多地方都做得不到位。比如用户上线下线广播功能也没完成（内部我已经提供了接口和方法，只是没有调用而已），有兴趣的朋友可以下载源代码去参考或帮忙完成这些功能。<br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/amf/" rel="tag">amf</a> , <a href="http://www.niuc.net/tags/%25E8%2581%258A%25E5%25A4%25A9%25E5%25AE%25A4/" rel="tag">聊天室</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7882/</link>
<title><![CDATA[Flex与.NET互操作(十三)：使用FluorineFx中的字节数组（ByteArray）实现图片上传]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Sat, 08 Aug 2009 06:33:02 +0000</pubDate> 
<guid>http://www.niuc.net/post/7882/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;前几天一位朋友问我一个问题，他说：“我用HTTP接口或是WebService接口可以实现图片上传功能，那么用FluorineFx如何实现图片上传功能呢？”，其实仔细看官方文档和示例程序的自己都可以找到答案，实现上传可以有很多种实现，这里我以官方所提供是示例为基础稍加改动，通过ByteArray类实现图片上传。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先建立FluorineFx库和网站，在远程服务器类里添加一个处理文件上传的方法，详细代码如下：<br/><br/><div class="code">namespace ByteStream.Services<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class ByteStreamService<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public ByteArray UploadImage(ByteArray ba)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemoryStream ms = new MemoryStream(ba.GetBuffer());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Image img = Bitmap.FromStream(ms);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bitmap newImage = new Bitmap(img);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemoryStream tempStream = new MemoryStream();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newImage.Save(tempStream, System.Drawing.Imaging.ImageFormat.Png);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string path = HttpContext.Current.Server.MapPath(&quot;UpLoad/ByteArray.png&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileStream fs = new FileStream(path, FileMode.Create);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempStream.WriteTo(fs);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs.Close();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByteArray result = new ByteArray(tempStream);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;处理图片上传的方法通过把flex客户端传递来的字节数组包装为内存流，然后通过写文件的形式将图片保存到指定的目录下。示例中提供了一个画图板，用户可以通过选择颜色自画不同的图象，然后保存到服务器上指定的目录。画图板的实现是根据鼠标按下的移动路线做的，代码如下：<br/><br/><div class="code">private function doMouseDown():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;x1 = myCanvas.mouseX;<br/>&nbsp;&nbsp;&nbsp;&nbsp;y1 = myCanvas.mouseY;<br/>&nbsp;&nbsp;&nbsp;&nbsp;isDrawing = true;<br/>}<br/>private function doMouseMove():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;x2 = myCanvas.mouseX;<br/>&nbsp;&nbsp;&nbsp;&nbsp;y2 = myCanvas.mouseY;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isDrawing)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myCanvas.graphics.lineStyle(2, drawColor);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myCanvas.graphics.moveTo(x1, y1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myCanvas.graphics.lineTo(x2, y2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x1 = x2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y1 = y2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/>private function doMouseUp():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;isDrawing = false;<br/>}<br/>//清空画图板<br/>private function onErase(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;myCanvas.graphics.clear();<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在官方实例中是使用的RemoteObject实现的，这里我将其修改为通过编程实现AMF通信实现当程序初始化的时候就建立与FluorineFx网关的AMF通信连接：<br/><br/><div class="code">private var nc:NetConnection;<br/>private var rs:Responder;<br/>private function init():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;rs = new Responder(onResult,onFault);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;http://localhost:2453/FluorineFxWeb/Gateway.aspx&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Flex客户端通过当前网络连接的call()方法实现远程方法调用，并指定通过Responder来处理服务器端方法的返回结果。<br/><br/><div class="code">private function onSaveImage(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var bd:BitmapData = new BitmapData(myCanvas.width,myCanvas.height);<br/>&nbsp;&nbsp;&nbsp;&nbsp;bd.draw(myCanvas);<br/>&nbsp;&nbsp;&nbsp;&nbsp;var ba:ByteArray = new PNGEncoder().encode(bd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.call(&quot;ByteStream.Services.ByteStreamService.UploadImage&quot;,rs,ba);<br/>}</div><br/> <br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">小提示：在进行Flex开发中，能够通过编程实现的最好通过编程实现，尽量少的去使用Flex组件，这样可以有效的给Flex程序瘦身。</div></div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;服务器端将传递过去的ByteArray数据返回到了客户端，客户端接收到这些数据通过处理将字节数组转化为显示对象后显示到界面上。<br/><br/><div class="code">private function onResult(result:ByteArray):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var loader:Loader = new Loader();<br/>&nbsp;&nbsp;&nbsp;&nbsp;loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderCompleteHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;loader.loadBytes(result);<br/>}<br/>private function loaderCompleteHandler(event:Event):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var loader:Loader = (event.target as LoaderInfo).loader;<br/>&nbsp;&nbsp;&nbsp;&nbsp;loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,loaderCompleteHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;var pictureHolder:UIComponent = new UIComponent();<br/>&nbsp;&nbsp;&nbsp;&nbsp;pictureHolder.addChild(loader);<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.resultImage.width = myCanvas.width;<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.resultImage.height = myCanvas.height;<br/>&nbsp;&nbsp;&nbsp;&nbsp;this.resultImage.addChild(pictureHolder);<br/>}<br/><br/>private function onFault(event:Object):void<br/>{}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;到此就完成了图片上传功能，下面是完整的Flex客户端代码：<br/><br/>Flex端完整代码<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot; fontSize=&quot;12&quot; creationComplete=&quot;init()&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.core.UIComponent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.Alert;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.events.ResizeEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.graphics.codec.PNGEncoder;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<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;private var isDrawing:Boolean=false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var x1:int;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var y1:int;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var x2:int;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var y2:int;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var drawColor:uint;<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;private var nc:NetConnection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var rs:Responder;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function init():void<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;rs = new Responder(onResult,onFault);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;http://localhost:2453/FluorineFxWeb/Gateway.aspx&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onSaveImage(event:MouseEvent):void<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;var bd:BitmapData = new BitmapData(myCanvas.width,myCanvas.height);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bd.draw(myCanvas);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var ba:ByteArray = new PNGEncoder().encode(bd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.call(&quot;ByteStream.Services.ByteStreamService.UploadImage&quot;,rs,ba);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onResult(result:ByteArray):void<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;var loader:Loader = new Loader();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderCompleteHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loader.loadBytes(result);<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;private function loaderCompleteHandler(event:Event):void<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;var loader:Loader = (event.target as LoaderInfo).loader;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,loaderCompleteHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var pictureHolder:UIComponent = new UIComponent();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pictureHolder.addChild(loader);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.resultImage.width = myCanvas.width;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.resultImage.height = myCanvas.height;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.resultImage.addChild(pictureHolder);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onFault(event:Object):void<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function doMouseDown():void<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;x1 = myCanvas.mouseX;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y1 = myCanvas.mouseY;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isDrawing = true;<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;private function doMouseMove():void<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;x2 = myCanvas.mouseX;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y2 = myCanvas.mouseY;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (isDrawing)<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;myCanvas.graphics.lineStyle(2, drawColor);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myCanvas.graphics.moveTo(x1, y1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myCanvas.graphics.lineTo(x2, y2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x1 = x2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y1 = y2;<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;&nbsp;&nbsp;&nbsp;&nbsp;private function doMouseUp():void<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;isDrawing = false;<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;//清空画图板<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onErase(event:MouseEvent):void<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;myCanvas.graphics.clear();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Panel x=&quot;10&quot; y=&quot;10&quot; width=&quot;348&quot; height=&quot;306&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Canvas x=&quot;10&quot; y=&quot;10&quot; width=&quot;315&quot; height=&quot;210&quot; id=&quot;myCanvas&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mouseDown=&quot;doMouseDown()&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mouseMove=&quot;doMouseMove()&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mouseUp=&quot;doMouseUp()&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Canvas&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:ControlBar&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:ColorPicker change=&quot;drawColor = event.target.selectedColor&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;清除&quot; click=&quot;onErase(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;保 存&quot; click=&quot;onSaveImage(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:ControlBar&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Panel&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Image x=&quot;382&quot; y=&quot;10&quot; id=&quot;resultImage&quot;/&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=255" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=255" target="_blank">http://www.niuc.net/attachment.php?fid=255</a><br/><br/><br/>本文例子下载：<a href="attachment.php?fid=256">点击这里下载文件</a><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/bytearray/" rel="tag">bytearray</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7881/</link>
<title><![CDATA[Flex与.NET互操作(十二)：FluorineFx的AMF(Action Message Format)协议通信]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Sat, 08 Aug 2009 02:27:00 +0000</pubDate> 
<guid>http://www.niuc.net/post/7881/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AMF(Action Message Format)在开发Flash/Flex应用中使用频率是非常高的，相对普通的HTTP、WebService的SOAP等多种数据通信方式的效率更高，有人曾经做过这方面的测试，详细可以访问：http://xinsync.xju.edu.cn/index.php/archives/2162。本文将结合FluorineFx来提供通信服务接口，在客户端通过Flex来访问，简单的介绍下关于使用FluorineFx的AMF(Action Message Format)协议通信的用法。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先建立一个FluorineFx服务库，并建立一个数据传输对象（DTO），为该对象添加<strong>[FluorineFx.TransferObject]</strong>表示该对象可以用作于FluorineFx的数据传输对象，这个对象将会在本文后面用到，如下代码块：<br/><br/><div class="code">namespace FxDotNet.Services.DTO<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;FluorineFx.TransferObject&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class Book<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public int ID { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Name { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Author { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public double Price { get; set; }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Book()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Book(int id, string name, string author, double price)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.ID = id;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Name = name;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Author = author;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Price = price;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;接下来就需要提供一个FluorineFx的远程服务（即标记有[RemotingService]的对象）,通过该服务提供对外访问的方法接口，如下代码块：<br/><br/><div class="code">namespace FxDotNet.Services<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class DataServices<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public DataServices()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 获取服务端的系统时间<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string GetServerTime()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return DateTime.Now.ToString();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public ArrayCollection GetBooks()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArrayCollection array = new ArrayCollection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array.Add(new Book(1, &quot;三国演义&quot;, &quot;罗贯中&quot;, 100.00));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array.Add(new Book(2, &quot;西游记&quot;, &quot;吴承恩&quot;, 200.00));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array.Add(new Book(3, &quot;水浒传&quot;, &quot;施耐庵&quot;, 300.00));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array.Add(new Book(4, &quot;红楼梦&quot;, &quot;曹雪芹&quot;, 400.00));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return array;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过FluorineFx网站来宿主该远程服务,通过Flex的配置文件services-config.xml配置远程访问的AMF连接通道。<br/><br/><div class="code">&lt;channels&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;channel-definition id=&quot;my-amf&quot; class=&quot;mx.messaging.channels.AMFChannel&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;endpoint uri=&quot;http://{server.name}:{server.port}/{context.root}/Gateway.aspx&quot; class=&quot;flex.messaging.endpoints.AMFEndpoint&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/channel-definition&gt;<br/>&lt;/channels&gt;</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx提供的远程服务(RemotingService),使用Flex、Flash或Silverlight开发的客户端都是可以访问的，要实现客户端的远程调用其实是很简单的，这里以Flex作为示例进行演示，设置通信协议为AMF3，然后直接调用当前连接到服务器端连接对象的call()方法就可以实现远程调用，详细请查看下面完整的Flex示例。<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot; creationComplete=&quot;init()&quot; fontSize=&quot;12&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.collections.ArrayCollection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.List;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var nc:NetConnection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var rs:Responder;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function init():void<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;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs = new Responder(onResult,onStatus);<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;nc.objectEncoding = ObjectEncoding.AMF3;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;http://localhost:2311/FxDotNet.Web/Gateway.aspx&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onResult(result:String):void<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;this.lbServerTime.text = &quot;服务端系统时间为：&quot; + result;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onStatus(event:Object):void<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;trace(&quot;Error&quot;);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function getServerTime(event:MouseEvent):void<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;//服务器端所提供的RemotingService的全限定名<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.call(&quot;FxDotNet.Services.DataServices.GetServerTime&quot;,rs);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&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;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;19&quot; y=&quot;28&quot; label=&quot;获取服务器系统时间&quot; click=&quot;getServerTime(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;19&quot; y=&quot;60&quot; width=&quot;402&quot; id=&quot;lbServerTime&quot;/&gt;<br/>&lt;/mx:Application&gt;</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;同样可以使用AMF来做大数据的传输，比如要传递一个集合、数组、DataTable或是DataSet等，下面以集合做为示例演示，ActionScript 3.0中新增了ArrayCollectin类，FluorineFx在服务器端对ActionScript 3.0的ArrayCollection对进行了序列化映射封装，服务端FluorineFx.AMF3.ArrayCollection类型的对象可以直接被客户端的ArrayCollection所接收。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上面FluorineFx所提供的远程服务接口中的GetBooks()方法，Flex调用此方法就会得到一个ArrayCollection对象，通过调试跟踪返回的数据可以很清楚的分析这些数据，如下图示：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=252" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=252" target="_blank">http://www.niuc.net/attachment.php?fid=252</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;详细请看下面的Flex完整示例代码：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot; fontSize=&quot;12&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;width=&quot;541&quot; height=&quot;302&quot; creationComplete=&quot;init()&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.collections.ArrayCollection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.List;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var nc:NetConnection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var rs:Responder;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function init():void<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;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs = new Responder(onResult,onFault);<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;nc.objectEncoding = ObjectEncoding.AMF3;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;http://localhost:2311/FxDotNet.Web/Gateway.aspx&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function getBook(event:MouseEvent):void<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;nc.call(&quot;FxDotNet.Services.DataServices.GetBooks&quot;,rs);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onResult(result:ArrayCollection):void<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;this.bookGrid.dataProvider = result;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onFault(event:Object):void<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;trace(&quot;Error&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;44&quot; y=&quot;46&quot; label=&quot;获取图书信息&quot; click=&quot;getBook(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &lt;mx:DataGrid x=&quot;44&quot; y=&quot;78&quot; id=&quot;bookGrid&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;编号&quot; dataField=&quot;ID&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;书名&quot; dataField=&quot;Name&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;作者&quot; dataField=&quot;Author&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;价格&quot; dataField=&quot;Price&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:DataGrid&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除了使用FluorineFx所提供的ArrayCollection外，同样可以使用我们熟悉的Object[],List&lt;Object&gt;,DataTable等常用类型来作为数据返回的类型，其中Object[]和List&lt;Object&gt;类型的数据返回到客户段能够直接被客户端所接收，如下使用Object[]作数据返回类型的代码块：<br/><br/><div class="code">/*************服务端方法*************/<br/>public Book&#91;&#93; GetBookArray()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;Book&#91;&#93; book = new Book&#91;&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(1, &quot;三国演义&quot;, &quot;罗贯中&quot;, 100.00),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(2, &quot;西游记&quot;, &quot;吴承恩&quot;, 200.00),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(3, &quot;水浒传&quot;, &quot;施耐庵&quot;, 300.00),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(4, &quot;红楼梦&quot;, &quot;曹雪芹&quot;, 400.00)<br/>&nbsp;&nbsp;&nbsp;&nbsp;};<br/>&nbsp;&nbsp;&nbsp;&nbsp;return book;<br/>}<br/>/*************客户端方法*************/<br/>private function onResult(result:Array):void<br/>{<br/>&nbsp;&nbsp; //<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是以List&lt;Object&gt;类型返回的代码示例代码，客户段可以使用ArrayCollection直接接收：<br/><br/><div class="code">/*************服务端方法*************/<br/>/// &lt;summary&gt;<br/>/// 以泛型类型返回给客户端<br/>/// &lt;/summary&gt;<br/>/// &lt;returns&gt;&lt;/returns&gt;<br/>public List&lt;Book&gt; GetBookList()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Book&gt; list = new List&lt;Book&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(1, &quot;三国演义&quot;, &quot;罗贯中&quot;, 100.00),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(2, &quot;西游记&quot;, &quot;吴承恩&quot;, 200.00),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(3, &quot;水浒传&quot;, &quot;施耐庵&quot;, 300.00),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Book(4, &quot;红楼梦&quot;, &quot;曹雪芹&quot;, 400.00)<br/>&nbsp;&nbsp;&nbsp;&nbsp;};<br/>&nbsp;&nbsp;&nbsp;&nbsp;return list;<br/>}<br/>/*************客户端方法*************/<br/>private function onResult(result:ArrayCollection):void<br/>{<br/>&nbsp;&nbsp; //<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果要使用DataTable类型做方法的数据返回类型就需要注意下，服务器端直接返回DataTable类型的数据客户端是不能直接接收解析的，要使客户断方便解析所返回的DataTable类型数据，FluorineFx提供了DataTableTypeAttribute，为返回DataTable类型的方法加上DataTableTypeAttribute后返回给客户端，客户端就可以直接使用ArrayCollection接收了。<br/><br/><div class="code">/******************服务端方法***********************/<br/>&#91;DataTableType(&quot;Book&quot;, &quot;FxDotNet.Services.DTO.Book&quot;)&#93;<br/>public DataTable GetBookTable()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp; DataTable dt = new DataTable(&quot;Book&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Columns.Add(&quot;ID&quot;, typeof(int));<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Columns.Add(&quot;Name&quot;, typeof(string));<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Columns.Add(&quot;Author&quot;, typeof(string));<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Columns.Add(&quot;Price&quot;, typeof(double));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; DataRow dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;ID&quot;&#93; = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Name&quot;&#93; = &quot;《三国演义》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Author&quot;&#93; = &quot;罗贯中&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Price&quot;&#93; = 100.00;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;ID&quot;&#93; = 2;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Name&quot;&#93; = &quot;《西游记》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Author&quot;&#93; = &quot;吴承恩&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Price&quot;&#93; = 200.00;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;ID&quot;&#93; = 3;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Name&quot;&#93; = &quot;《水浒传》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Author&quot;&#93; = &quot;施耐庵&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Price&quot;&#93; = 300.00;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;ID&quot;&#93; = 4;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Name&quot;&#93; = &quot;《红楼梦》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Author&quot;&#93; = &quot;曹雪芹&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dr&#91;&quot;Price&quot;&#93; = 400.00;<br/>&nbsp;&nbsp;&nbsp;&nbsp; dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; return dt;<br/>}<br/>/******************客户端方法***********************/<br/>private function onResult(result:ArrayCollection):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//do other<br/>}</div><br/><br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=253" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=253" target="_blank">http://www.niuc.net/attachment.php?fid=253</a><br/><br/><br/>关于FluorineFx的AMF就简单介绍这些，本文例子下载：<a href="attachment.php?fid=254">点击这里下载文件</a><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/amf/" rel="tag">amf</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7880/</link>
<title><![CDATA[Flex与.NET互操作(十一)：FluorineFx.Net实现视频录制与视频回放]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Fri, 07 Aug 2009 07:44:38 +0000</pubDate> 
<guid>http://www.niuc.net/post/7880/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本文主要介绍使用FluorineFx.Net来实现视频录制与视频回放，FluorineFx如同FMS一样，除了有AMF通信，RTMP协议，RPC和远程共享对象外，它同样具备视频流服务的功能。通过它我们可以非常方便的实现在线视频录制、视频直播、视频聊天以及视频会议等类似应用程序的开发。 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先我们来看看使用FluorineFx服务端是如何开发的，建立ApplicationAdapter是必然的，这里我们为本文中的示例程序建立的ApplicationAdapter为VideoApplication，并为其添加RemotingServiceAttribute如下代码块：<br/><br/><div class="code">namespace Fx.Adapter<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// 视频应用<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class VideoApplication : ApplicationAdapter<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override bool AppStart(IScope application)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return base.AppStart(application);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override bool AppConnect(IConnection connection, object&#91;&#93; parameters)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return base.AppConnect(connection, parameters);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ApplicationAdapter模板所提供的方法在实际项目开发中根据自己的需求去重写，这里不作过多介绍。光是这样还是不能实现视频的录制和回放的功能，这只是实现了基本的启动应用程序和客户端连接等基本功能，要想实现视频录制和回放，我们还得让VideoApplication实现IStreamService接口，该接口提供了实现视频发布和播放的相应功能，其定义如下：<br/><br/><div class="code">namespace FluorineFx.Messaging.Api.Stream<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;CLSCompliant(false)&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public interface IStreamService : IScopeService, IService<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void closeStream();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int createStream();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void deleteStream(int streamId);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void deleteStream(IStreamCapableConnection connection, int streamId);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void pause(bool pausePlayback, double position);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void play(bool dontStop);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void play(string name);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void play(string name, double start);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void play(string name, double start, double length);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void play(string name, double start, double length, bool flushPlaylist);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void publish(bool dontStop);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void publish(string name);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void publish(string name, string mode);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void receiveAudio(bool receive);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void receiveVideo(bool receive);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void releaseStream(string streamName);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void seek(double position);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OK，有了应用处理器接下来在FluorineFx网站的apps中添加应用程序（VideoApp），并配置好由此处理器来处理视频录制和回放。<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;configuration&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;application-handler type=&quot;Fx.Adapter.VideoApplication&quot;/&gt;<br/>&lt;/configuration&gt;</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;要使用RTMP协议，那么配置RTMP通信信道肯定是不能少的，在配置文件WEB-INF/flex/service-config.xml中配置使用RTMP协议的通信信道。<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;<br/>&lt;services-config&gt;<br/>&nbsp;&nbsp;&lt;channels&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;channel-definition id=&quot;my-rtmp&quot; class=&quot;mx.messaging.channels.RTMPChannel&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;endpoint uri=&quot;rtmp://{server.name}:1617&quot; class=&quot;flex.messaging.endpoints.RTMPEndpoint&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/channel-definition&gt;<br/>&nbsp;&nbsp;&lt;/channels&gt;<br/>&lt;/services-config&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 于此FluorineFx服务器端“基本”算是完成了。下面转到客户端的开发，建立Flex项目并设计好界面，如下图：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=248" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=248" target="_blank">http://www.niuc.net/attachment.php?fid=248</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;建立与FluorineFx服务器上应用程序的连接，连接成功则将自己的视频数据显示到界面上，如下实现代码：<br/><br/><div class="code">private function connectionServer(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;rtmp://localhost:1617/VideoRecord&quot;,&quot;beniao&quot;,&quot;123456&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStautsHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<br/>}<br/><br/>private function onNetStautsHandler(event:NetStatusEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(event.info.code == &quot;NetConnection.Connect.Success&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cam = Camera.getCamera();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(cam != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.myVideo.attachCamera(cam);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alert.yesLabel = &quot;确定&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alert.show(&quot;没有检测到视频摄像头&quot;,&quot;系统提示&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;录制视频也就是将自己本机的视频摄像头获取的视频数据以及音频设备的数据附加到网络流（NetStream），使用网络流的publish()方法将流发布到服务器上，这和使用FMS是相同的。<br/><br/><div class="code">private function onRecordVideo(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(this.nc)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var mic:Microphone = Microphone.getMicrophone();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns = new NetStream(this.nc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.attachCamera(cam);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.attachAudio(mic);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.client = this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.publish(this.videoName.text,&quot;record&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.btnStart.enabled = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.btnEnd.enabled = true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/><br/>private function onStopRecord(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(this.nc)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.nc.close();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.btnStart.enabled = true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.btnEnd.enabled = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.btnPlay.enabled = true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;停止视频录制的功能就更加简单了，直接断开当前客户端与服务器端的连接就可以，使用网络连接(NetConnection)的close()方法。 <br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=249" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=249" target="_blank">http://www.niuc.net/attachment.php?fid=249</a><br/><br/>&nbsp;&nbsp; 录制好的视频将会保存在网站下的apps/VideoApp/stream目录中，如下图：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=250" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=250" target="_blank">http://www.niuc.net/attachment.php?fid=250</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;实现录制的视频回放实际上就是播放服务器上的一个.flv视频文件，同样需要先建立与服务器端的网络连接，通过网络流去加载指定的视频文件，最后将其显示到应用界面上。<br/><br/><div class="code">private function onPlayVideo(event:MouseEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;rtmp://localhost:1617/VideoRecord&quot;,&quot;beniao&quot;,&quot;123456&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.addEventListener(NetStatusEvent.NET_STATUS,onPlayNetStautsHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<br/>}<br/>private function onPlayNetStautsHandler(event:NetStatusEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(event.info.code == &quot;NetConnection.Connect.Success&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns = new NetStream(this.nc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ns.client = this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var video:Video = new Video();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;video.width = 320;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;video.height = 240;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;video.attachNetStream(this.ns);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.myVideo.addChild(video);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.ns.play(this.videoName.text);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;到此就完成了使用FluorineFx.Net来实现视频录制和回放的功能，接下来我们来看看FluorineFx对发布录制视频流以及实况视频流的安全方面是怎么处理的。FluorineFx.Messaging.Api.Stream.IStreamPublishSecurity接口就是专门用来处理发布流是的安全处理的，如果要对发布流进行安全方面的处理，那么就自定义一个实现该接口的安全策略类，在策略类里根据自己的实际情况来处理安全设置。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过该安全策略类可以很方便的判断发布流的类型、流的名称以及对发布流进行授权等相关操作。如下安全策略类：<br/><br/><div class="code">namespace Fx.Adapter<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class PublishSecurity : IStreamPublishSecurity<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public bool IsPublishAllowed(IScope scope, string name, string mode)<br/>&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;&nbsp;&nbsp;&nbsp;&nbsp;if (!&quot;record&quot;.Equals(mode))<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;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//文件名是否以test开头<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!name.StartsWith(&quot;test&quot;))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在应用处理程序里通过ApplicationAdapter提供的RegisterStreamPublishSecurity()方法注册安全策略，该方法的定义如下所示：<br/><br/><div class="code">public void RegisterStreamPublishSecurity(IStreamPublishSecurity handler); </div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;要注册发布流的安全策略，通常都是在应用程序启动中注册，如下代码块：<br/><br/><div class="code">public override bool AppStart(IScope application)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;RegisterStreamPublishSecurity(new PublishSecurity());<br/>&nbsp;&nbsp;&nbsp;&nbsp;return base.AppStart(application);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过RegisterStreamPublishSecurity()方法注册好发布流的安全策略后，每次发布流都会通过自定义的安全策略来检测当前发布流是否符合自定义的安全规则。这样一方便可以保证别人恶意连接到你的应用程序进行流的发布，消耗网络带宽等多中不利现象，更多的好处还待研究。<br/><br/>本文示例程序下载： <a href="attachment.php?fid=251">点击这里下载文件</a><br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/%25E5%25BD%2595%25E5%2588%25B6/" rel="tag">录制</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7879/</link>
<title><![CDATA[Flex与.NET互操作(十)：FluorineFx.Net的及时通信应用(Remote Shared Objects）]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Fri, 07 Aug 2009 04:39:15 +0000</pubDate> 
<guid>http://www.niuc.net/post/7879/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;远程共享对象(Remote Shared Objects) 可以用来跟踪、存储、共享以及做多客户端的数据同步操作。只要共享对象上的数据发生了改变，将会把最新数据同步到所有连接到该共享对象的应用程序客户端。FluorineFx所提供的远程共享对象(Remote Shared Objects)和FMS的共享对象的功能是一样，对于熟悉FMS开发的朋友来说,学习FluorineFx的远程共享对象是非常简单的。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;共享对象可以在服务器端创建，也可以在客户端创建。在客户端创建共享对象的方法和使用FMS开发是一样的，创建一个NetConnection对象，通过该对象的connect()方法连接到服务器，然后通过SharedObject.getRemote()方法就可以在客户端创建一个远程共享对象。如下实例代码：<br/><br/><div class="code">private function connectionServer():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var nc:NetConnection = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;rtmp://localhost:1617/SOAPP&quot;,&quot;username&quot;,&quot;password&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<br/>}<br/><br/>private function onStatusHandler(event:NetStatusEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(event.info.code == &quot;NetConnectin.Connect.Success&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createSharedObject();<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}<br/><br/>private function createSharedObject():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var so:SharedObject = SharedObject.getRemote(&quot;OnLineUsers&quot;,nc.uri,false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;so.addEventListener(SyncEvent.SYNC,onSyncHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;so.connect(this.nc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;so.client = this;<br/>}<br/><br/>private function onSyncHandler(event:SyncEvent):void<br/>{<br/>&nbsp;&nbsp;//...do other<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在FluorineFx的服务器端创建远程共享对象和FMS有很大的区别，FluorineFx的ISharedObjectService接口提供了专门用于创建远程共享对象的方法CreateSharedObject()，ApplicationAdapter实现了此接口方法。定义如下：<br/><br/><div class="code">public bool CreateSharedObject(IScope scope, string name, bool persistent)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ISharedObjectService service = (ISharedObjectService)ScopeUtils.GetScopeService(scope, typeof(ISharedObjectService));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return service.CreateSharedObject(scope, name, persistent);<br/>}</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果要在服务器端创建远程共享对象，直接调用ApplicationAdapter类中的CreateSharedObject()方法就可以。如下在FluorineFx服务器端创建远程共享对象的代码块：<br/><br/><div class="code">ISharedObject users_so = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/>if (users_so == null)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建共享对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CreateSharedObject(connection.Scope, &quot;OnLineUsers&quot;, false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users_so = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;要想更新共享对象里的数据客户端还是使用setProperty()方法，而FluorineFx的服务器更新共享对象的方法则与FMS不一样，使用的是FluorineFx.Messaging.Api.IAttributeStore接口提供的SetAttribute()和RemoveAttribute()方法来更新共享对象里的数据。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;陆续介绍了这么多，下面通过一个案例来看看该这么去应用远程共享对象。比如做IM、视频聊天、视频会议等及时通信类型的应用中，用户上线下线的频率非常高，这时候我们就可以使用远程共享对象去做在线用户的数据同步。 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先建立FluorineFx服务库，并建立一个应用类继承于ApplicationAdapter,通过重写ApplicationAdapter的相关方法来实现应用程序的不同需求，详细如下代码块：<br/><br/><div class="code">using System;<br/>using System.Collections.Generic;<br/>using System.Text;<br/>using FluorineFx.Messaging.Adapter;<br/>using FluorineFx;<br/>using FluorineFx.Messaging.Api;<br/>using System.Diagnostics;<br/>using FluorineFx.Messaging.Api.SO;<br/>using FluorineFx.Exceptions;<br/>using FluorineFx.Context;<br/>using FluorineFx.Messaging.Api.Service;<br/>using System.Collections;<br/>using Fx.Adapter.DTO;<br/><br/>namespace Fx.Adapter<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// 自定义ApplicationAdapter<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class MyApp : ApplicationAdapter<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 应用程序启动<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;application&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override bool AppStart(IScope application)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Trace.WriteLine(&quot;应用程序启动&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 房间启动<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;room&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override bool RoomStart(IScope room)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Trace.WriteLine(&quot;房间启动&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!base.RoomStart(room))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 接收客户端的连接<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;connection&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;parameters&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override bool AppConnect(IConnection connection, object&#91;&#93; parameters)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string userName = parameters&#91;0&#93; as string;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string password = parameters&#91;1&#93; as string;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (password == null &#124;&#124; password == string.Empty)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new ClientRejectedException(null);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.Client.SetAttribute(&quot;userName&quot;, userName);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//获取共享对象(OnLineUsers)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ISharedObject users_so = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (users_so == null)<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;//创建共享对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CreateSharedObject(connection.Scope, &quot;OnLineUsers&quot;, false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users_so = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<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;//更新共享对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users_so.SetAttribute(userName, userName);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 加入房间<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;client&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;room&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override bool RoomJoin(IClient client, IScope room)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Trace.WriteLine(&quot;加入房间 &quot; + room.Name);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 离开房间<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;client&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;room&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override void RoomLeave(IClient client, IScope room)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Trace.WriteLine(&quot;离开房间 &quot; + room.Name);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base.RoomLeave(client, room);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 用户退出<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;connection&quot;&gt;&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public override void AppDisconnect(IConnection connection)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string userName = connection.Client.GetAttribute(&quot;userName&quot;) as string;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ISharedObject users_so = GetSharedObject(connection.Scope, &quot;OnLineUsers&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (users_so != null)<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;//从共享对象中移除当前退出系统用户<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;users_so.RemoveAttribute(userName);<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;base.AppDisconnect(connection);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;开发好了ApplicationAdapter，还需要对此ApplicationAdapter进行通信配置，在FluorineFx的应用程序目录中添加app.config并进行如下配置：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;configuration&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;application-handler type=&quot;Fx.Adapter.MyApp&quot;/&gt;<br/>&lt;/configuration&gt;</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;另外还需要配置一个客户端方法的通信通道，通过FluorineFx网站下的WEB-INF/flex/service-config.xml配置：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;<br/>&lt;services-config&gt;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;channels&gt;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;channel-definition id=&quot;my-rtmp&quot; class=&quot;mx.messaging.channels.RTMPChannel&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;endpoint uri=&quot;rtmp://{server.name}:1617&quot; class=&quot;flex.messaging.endpoints.RTMPEndpoint&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/channel-definition&gt;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/channels&gt;<br/><br/>&lt;/services-config&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上便完成了服务器端的开发，在flash/felx客户端通过NetConnection去连接应用，并根据当前的连接去连接服务器端的远程共享对象，最后通过异步事件来实现数据同步更新。如下程序运行截图：<br/><a href="http://www.niuc.net/attachment.php?fid=246" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=246" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此时开多个浏览器窗口测试，不同窗口使用不同的用户名登录，可以很清楚的看到，我们已经实现了在线用户的数据同步功能，可以及时的反映用户上线离线，可以及时的同步在线用户列表的数据。 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;另外远程共享对象还有一个功能非常强大的特性方法，就是连接到共享对象的客户端之间可以直接广播消息（客户端调用客户端的方法）。就以上面在线用户的案例为例，用户成功登陆服务器我需要广播一条消息，用户退出了我也需要广播一条消息，要实现这个功能就需要通过远程共享的客户端呼叫(send()方法)来实现，如下代码块：<br/><br/><div class="code">private function onCallClient(message:String):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;so.send(&quot;onSayMessage&quot;,message);<br/>}</div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;远程共享对象的send()方法调用了onSayMessage这个客户端方法来实现对连接到共享对象上的所有客户端广播消息，那么我们的在定义一个onSayMessage方法，如下：<br/><br/><div class="code">/**<br/> * 接受客户端呼叫---此方法必须是public修饰<br/> */<br/>public function onSayMessage(message:Object):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;traceWriteln(message.toString());<br/>}<br/><br/>private function traceWriteln(param:String):void<br/>{<br/>&nbsp;&nbsp; txtTraceArea.htmlText += param + &quot;&#92;n&quot;;<br/>&nbsp;&nbsp; txtTraceArea.validateNow();<br/>&nbsp;&nbsp; txtTraceArea.verticalScrollPosition = txtTraceArea.maxVerticalScrollPosition;<br/>}</div><br/><br/><a href="http://www.niuc.net/attachment.php?fid=247" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=247" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果想实现用户退出广播，可以通过服务器端RPC的方法调用客户端的方法来实现，关于RPC请查看上一篇教程，有详细介绍。下面是Flex客户端的完整代码：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;width=&quot;530&quot; height=&quot;378&quot; backgroundGradientAlphas=&quot;&#91;1.0, 1.0&#93;&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;backgroundGradientColors=&quot;&#91;#000000, #686868&#93;&quot; fontSize=&quot;12&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.Alert;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import dotnet.fluorinefx.VO.UserInfo;<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;private var nc:NetConnection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var so:SharedObject;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var info:UserInfo;<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;private function connectionServer(event:MouseEvent):void<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;info = new UserInfo();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info.UserName = this.txtUserName.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info.Password = this.txtPassword.text;<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;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;rtmp://localhost:1617/SOAPP&quot;,info.UserName,info.Password);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<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;this.txtUserName.text=&quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.txtPassword.text=&quot;&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.txtUserName.setFocus();<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onStatusHandler(event:NetStatusEvent):void<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;this.connStatus.text = &quot;连接状态：&quot; + event.info.code;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(event.info.code == &quot;NetConnection.Connect.Success&quot;)<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;//连接远程共享对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;so = SharedObject.getRemote(&quot;OnLineUsers&quot;,nc.uri,false);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(so)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;so.addEventListener(SyncEvent.SYNC,onSyncHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;so.connect(nc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;so.client = this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&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;onCallClient(&quot;用户【 &lt;font color=&#92;&quot;#4100b9&#92;&quot;&gt;&quot;+info.UserName+&quot;&lt;/font&gt;】登陆了系统！&quot;);<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;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onSyncHandler(event:SyncEvent):void<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;var temp:Array = new Array();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(var u:String in so.data)<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;//traceWriteln(&quot;异步事件-&gt;共享对象：&quot; + u + &quot;:&quot; + so.data&#91;u&#93;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp.push(so.data&#91;u&#93;);<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;this.userList.dataProvider = temp;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function traceWriteln(param:String):void<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;txtTraceArea.htmlText += param + &quot;&#92;n&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txtTraceArea.validateNow();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txtTraceArea.verticalScrollPosition = txtTraceArea.maxVerticalScrollPosition;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onCallClient(message:String):void<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;so.send(&quot;onSayMessage&quot;,message);<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;/**<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; */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public function onSayMessage(message:Object):void<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;traceWriteln(message.toString());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;24&quot; y=&quot;134&quot; id=&quot;connStatus&quot; width=&quot;288&quot; color=&quot;#FFFFFF&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:List x=&quot;342&quot; y=&quot;10&quot; height=&quot;347&quot; width=&quot;160&quot; id=&quot;userList&quot; &gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:List&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Form x=&quot;24&quot; y=&quot;10&quot; width=&quot;236&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:FormItem label=&quot;用户名：&quot; color=&quot;#FFFFFF&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput id=&quot;txtUserName&quot; width=&quot;130&quot; color=&quot;#000000&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:FormItem&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:FormItem label=&quot;密&nbsp;&nbsp;码：&quot; color=&quot;#FFFFFF&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput id=&quot;txtPassword&quot; width=&quot;130&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color=&quot;#000000&quot; displayAsPassword=&quot;true&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:FormItem&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:FormItem label=&quot;&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;登陆服务器&quot; click=&quot;connectionServer(event)&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enabled=&quot;{this.txtUserName.text.length&amp;gt;0?true:false}&quot; color=&quot;#FFFFFF&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:FormItem&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Form&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextArea x=&quot;24&quot; y=&quot;174&quot; width=&quot;288&quot; height=&quot;153&quot; alpha=&quot;1.0&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;backgroundColor=&quot;#F2D2D2&quot; backgroundAlpha=&quot;0.26&quot; color=&quot;#FFFFFF&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id=&quot;txtTraceArea&quot; borderColor=&quot;#FFFFFF&quot;/&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/rso/" rel="tag">rso</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/alias/eclipse-ruby-rdt/</link>
<title><![CDATA[使用 Eclipse 插件 Ruby Development Tools（RDT）开发RUBY]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[杂谈]]></category>
<pubDate>Fri, 07 Aug 2009 02:44:48 +0000</pubDate> 
<guid>http://www.niuc.net/alias/eclipse-ruby-rdt/</guid> 
<description>
<![CDATA[ 
	本文介绍如何使用 Eclipse 插件 Ruby Development Tools（RDT），这个插件使 Eclipse 能够成为一流的 Ruby 开发环境。那些希望利用 Eclipse 社区丰富的基础设施来支持开发的 Ruby 开发人员会从本文中受益，对有兴趣使用 Ruby 的 Java™ 开发人员也会有所收获。<br/><br/>............<br/><br/>Tags - <a href="http://www.niuc.net/tags/ruby/" rel="tag">ruby</a> , <a href="http://www.niuc.net/tags/eclipse/" rel="tag">eclipse</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/alias/mp4-file-format/</link>
<title><![CDATA[mp4（H264容器）的详细文件格式分析]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Dot-Net技术]]></category>
<pubDate>Thu, 06 Aug 2009 07:19:03 +0000</pubDate> 
<guid>http://www.niuc.net/alias/mp4-file-format/</guid> 
<description>
<![CDATA[ 
	MP4文件的详细格式分析！<br/>............<br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/mp4%25E6%2596%2587%25E4%25BB%25B6%25E6%25A0%25BC%25E5%25BC%258F/" rel="tag">mp4文件格式</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7878/</link>
<title><![CDATA[Flex与.NET互操作(九)：FluorineFx.Net的及时通信应用（Remote Procedure Call）]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Thu, 06 Aug 2009 05:35:08 +0000</pubDate> 
<guid>http://www.niuc.net/post/7878/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FluorineFx.NET提供了完善的RPC(Remote Procedure Call)功能，无论是通过Flash还是Flex开发的客户端应用(.swf)都可以非常简单方便的采用RPC的方式调用.NET的服务器端方法，.NET的服务器端同样也可以非常方便的呼叫客户端,调用客户端的方法(比如实现系统广播)。<br/><br/><strong>一、客户端的RPC（客户端调用服务器端）</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 要想实现客户端访问服务器端的方法，首先得对ActionScript中的NetConnection比较熟悉，该类提供了一个示例方法call()专们用来做RPC访问，该方法的定义如下:<br/><br/><div class="code">public function call(command:String, responder:Responder, ... arguments):void </div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;比如说我们在开发一个及时应用的时候，所有的客户端都需要同步服务器的系统时间，这个时候我们就可以在服务器端提供一个返回当前系统时间的方法给客户端调用。如下:<br/><br/><div class="code">//返回当前系统时间<br/>public string GetServerTime()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp; return DateTime.Now.ToString();<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有了这个方法客户端就可以通过NetConnection的call()方法实行远程调用了,并通过Responder来处理调用的结果，如果所调用的服务器端方法没有返回值，则在调用的时候可以不使用Responder。如下完整的Flex实例代码：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot; fontSize=&quot;12&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.Alert;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var nc:NetConnection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var responder:Responder = new Responder(onResult,onError);<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;private function connectionServer(event:MouseEvent):void<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;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;rtmp://localhost:1617/RPCDemo&quot;,&quot;abc&quot;,&quot;123&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.client = this;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onStatusHandler(event:NetStatusEvent):void<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;this.connStatus.text = &quot;连接状态：&quot; + event.info.code;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(event.info.code == &quot;NetConnection.Connect.Success&quot;)<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;trace(&quot;连接服务器成功&quot;);<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;private function onGetServerTime(event:MouseEvent):void<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;nc.call(&quot;GetServerTime&quot;,responder);<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;<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;private function onResult(result:String):void<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;this.txtResult.text = &quot;方法GetServerTime返回结果&quot; + result;<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;<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;private function onError(event:Event):void<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;trace(&quot;调用服务器端方法出错&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;30&quot; y=&quot;43&quot; label=&quot;连接服务器&quot; click=&quot;connectionServer(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;30&quot; y=&quot;75&quot; width=&quot;296&quot; id=&quot;connStatus&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;30&quot; y=&quot;112&quot; label=&quot;调用服务端方法&quot; click=&quot;onGetServerTime(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;30&quot; y=&quot;153&quot; id=&quot;txtResult&quot; width=&quot;296&quot;/&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx.Net的RPC就这么简单，客户端调用服务器端的方法，直接通过当前连接的call()方法调用，使用Responder来处理调用的结果。<br/><br/><strong>二、服务器端的RPC（服务器端调用客户端）</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;客户端和服务器端的调用是可以双向的，服务器端也同样可以调用客户端的方法。无论是客户端还是服务器端，相互调用始终都是离不开当前的连接对象。如上面客户端是通过当前连接的call()方法实现的调用服务器端方法，那么服务器端调用客户端的方法同样如此，也是通过当前连接对象来处理。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FluorineFx中用于连接的接口是IConnection，只要客户端成功的连接上了服务器端，那么在服务器端就会保存所有连接到服务器端的连接对象的各种属性。实现调用客户端方法的则是IServiceCapableConnection接口，IServiceCapableConnection接口的定义如下所示：<br/><a href="http://www.niuc.net/attachment.php?fid=245" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=245" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果要想实现服务器端调用客户端的方法，则必须使用此接口来完成，需要将当前连接的接口IConnection强制转化为<br/><br/>IServiceCapableConnection接口，然后调用其invoke()方法来完成服务器端对客户端方法的调用。<br/><br/><div class="code">/// &lt;summary&gt;<br/>/// 调用客户端的方法<br/>/// &lt;/summary&gt;<br/>/// &lt;param name=&quot;connection&quot;&gt;&lt;/param&gt;<br/>public void InvokeClient()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;IServiceCapableConnection conn = FluorineContext.Current.Connection as IServiceCapableConnection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (connection != null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object&#91;&#93; args = new object&#91;&#93; { GetServerTime() };<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.Invoke(&quot;RecServerMessage&quot;, args);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在服务器端可以通过FluorineContext.Current.Connection获取到当前客户端的连接对象，然后将其转化为IServiceCapableConnection接口对象，调用其Invoke()方法便可实现调用客户端的方法。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里需要注意一点就是，提供给服务器端调用的客户端方法必须是公共方法（public修饰的方法）,否则服务器端会报"Not found method:方法名"的异常。如下代码块：<br/><br/><div class="code">/**<br/> * 接收服务器端的调用方法<br/> * */<br/>public function RecServerMessage(message:Object):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;Alert.show(message.toString());<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FluorineFx.Net所提供的上面这两种功能是非常实用的，特别是在开发及时应用的时候，客户端RPC可以方便是实现将客户端是数据请求到服务器端进行处理，比如开发网络游戏中，游戏客户端的不同数据随时都在改变，那么我们就可以使用客户端RPC来实现这一需求。服务器端RPC同样可以应用于此，游戏中的数据变化了通过客户端RPC请求到服务器端，服务器端进行相与的业务计算和处理之后将客户端需要的数据通过服务器端RPC返回到当前请求的客户端。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;或许有的朋友会想或是问到，如果我要开发一个聊天室，要实现系统广播消息是不是可以使用这种方式来实现。答案是肯定的，系统要广播消息，可以从服务器端获取到所有连接到服务器端的客户端，然后循环的调用客户端的方法来实现系统广播消息。关于如何实现系统广播这里我就不作介绍，因为FluorineFx.Net为我们提供了更好的方式来实现系统广播。有兴趣的朋友请关注我的后续文章，在下一篇文章里我将详细介绍这方面的知识点。<br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/rpc/" rel="tag">rpc</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7884/</link>
<title><![CDATA[C++ 和 C# 的数据类型对照]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[Dot-Net技术]]></category>
<pubDate>Wed, 05 Aug 2009 07:55:31 +0000</pubDate> 
<guid>http://www.niuc.net/post/7884/</guid> 
<description>
<![CDATA[ 
	C#调用VC++的dll最主要的问题之一就是数据类型对应了！本文从互联网上摘录了详细的C++与C#的类型对照信息！<br/>............<br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/c%2523%25E8%25B0%2583%25E7%2594%25A8c%252B%252B/" rel="tag">c#调用c++</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7877/</link>
<title><![CDATA[Flex与.NET互操作(八)：FluorineFx.Net的及时通信应用（ApplicationAdapter）]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Wed, 05 Aug 2009 03:29:41 +0000</pubDate> 
<guid>http://www.niuc.net/post/7877/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用FluorineFx.Net开发的每一个实时通讯功能应用都拥有一个应用程序适配器（ApplicationAdapter），用来管理整个实时通讯应用的生命周期，以及接受和拒绝客户端的连接等。应用程序适配器对象也就相当于是一个Flash媒体服务器应用程序的对象。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用FluorineFx.Net开发及时通信应用，我们可以通过ASP.NET网站来宿主，一个ASP.NET网站可以承载多个实时通讯应用程序。这些应用程序都存储ASP.NET网站的根目录下指定文件夹的根目录中。如下图示：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=241" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=241" target="_blank">http://www.niuc.net/attachment.php?fid=241</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在开发FluorineFx的及时通信应用的时候，按照FluorineFx的目录结构配置ASP.NET的站点目录是非常简单的，只需要在ASP.NET站点下面建立一个名为apps的目录，那么FluorineFx就会认为此目录下的每一个文件夹就表示一个FluorineFx应用。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们可以通过FluorineFx来开发及时文字聊天、视频聊天、视频录制、媒体播放程序以及WebGame等类似及时应用程序。比如我们需要开发一个视频聊天系统，OK，那便在ASP.NET站点目录下建立一个apps目录，然后在apps下建立一个名为VideoChat的目录，如下目录结构：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=242" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=242" target="_blank">http://www.niuc.net/attachment.php?fid=242</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在Flash或是Flex客户端，我们就可以使用下面的代码来连到这个基于FluorineFx的视频聊天应用。<br/><br/><div class="code">private var ns:NetConnection;<br/>public function ConnectionFxApp():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;ns = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;ns.connect(&quot;rtmp://localhost:1974/VideoChat&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;ns.client=this;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ns.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);<br/>}<br/><br/>private function onNetStatusHandler(evt:NetStatusEvent):void<br/>{}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;每个应用程序都有其自己的应用范围和层次的根源，这和FMS、Red5是一样的规律。无论是范围还是层次，他都有一个唯一的名字（应用名、实例名等）来区分，我们也可以叫他们为应用程序的实例。这些实例可以是聊天室房间、视频流以及共享对象等。&nbsp;&nbsp; <br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=243" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=243" target="_blank">http://www.niuc.net/attachment.php?fid=243</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这些其实是非常容易理解的，如上图示的聊天室房间分配，分别有Room1,Room2,Room3三个聊天房间，那么对于VideoChat这个聊天应用来说要进行视频聊天就有三条连接线路，分别是：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、http://localhost:1974/VideoChat/Room1<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、http://localhost:1974/VideoChat/Room2<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、http://localhost:1974/VideoChat/Room3<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除了聊天室和应用的层次外，应用程序里还有诸入视频流、共享对象等。他们可以共同应用，也可以为不同的房间分别建立不同的共享对象，如果你要想实现不同房间里的用户可以相互聊天不想让别的房间的人看到，OK，此时你就可以为该房间独立创建一个共享对象来实现。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当开发程序需要去连接客户端，处理服务端事件、调用客户端方法等，就需要自定义一个应用程序适配器（ApplicationAdapter），此适配器必须继承并实现FluorineFx.Messaging.Adapter.ApplicationAdapter。FluorineFx.Messaging.Adapter.ApplicationAdapter做为一个新的应用程序的基类，提供了客户端与应用程序之间通信的接口方法、数据流以及共享对象等。它能够时时处理应用程序的启动、停止、客户端的连接和断开。<br/>[img]attachment.php?fid=244[/img<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Flash或是Flex客户端，我们可以通过NetConnectin.call()调用应用程序适配器的方法。如下示例代码块：<br/><br/>服务器端应用适配器所定义的代码：<br/><br/><div class="code">public class Application : ApplicationAdapter<br/>{<br/>&nbsp;&nbsp; public string Echo(string msg)<br/>&nbsp;&nbsp; {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &quot;Echo: &quot; + msg;<br/>&nbsp;&nbsp; }<br/>}</div><br/><br/>Flash/Flex客户端可以通过以下代码块调用服务器端的方法：<br/><br/><div class="code">private var ns:NetConnection;<br/>private function CallServerMethod():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc = new NetConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.connect(&quot;rtmp://localhost:1974/application&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.onResult = function(obj) <br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trace(&quot;The result is &quot; + obj);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;nc.call(&quot;Echo&quot;, nc, &quot;Hello&quot;);<br/>}</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 本文就先介绍到这里，下篇将接着本篇介绍FluorineFx.NET中客户端调用服务器端方法和服务器端呼叫客户端的方法。<br/><br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/applicationadapter/" rel="tag">applicationadapter</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7876/</link>
<title><![CDATA[Flex与.NET互操作(七)：FluorineFx.NET的认证(Authentication )与授权(Authorization)]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Tue, 04 Aug 2009 02:23:18 +0000</pubDate> 
<guid>http://www.niuc.net/post/7876/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FluorineFx.NET的认证(Authentication )与授权(Authorization)和ASP.NET中的大同小异,核实用户的身份既为认证，授权则是确定一个用户是否有某种执行权限，应用程序可根据用户信息授予和拒绝执行。FluorineFx.NET的认证和授权使用.Net Framework基于角色的安全性的支持。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;比如说我们需要自定义一个认证与授权的方案，指定那些远程服务上的那些方法将要被认证或授权以及授权用户角色组等，我们就需要自定义一个LoginCommand并实现ILoginCommand接口或者继承于FluorineFx.Security.GenericLoginCommand(此类实现了ILoginCommand接口)基类。接口定义如下：<br/><br/><div class="code">namespace FluorineFx.Security<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;public interface ILoginCommand<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IPrincipal DoAuthentication(string username, Hashtable credentials);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool DoAuthorization(IPrincipal principal, IList roles);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool Logout(IPrincipal principal);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void Start();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void Stop();<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;网关通过调用该接口中的方法DoAuthentication()来实现验证，具体的验证规则我们可以自定义（重写方法的实现）。<br/><br/><div class="code">/// &lt;summary&gt;<br/>/// 自定义 LoginCommand<br/>/// &lt;/summary&gt;<br/>public class LoginCommand : GenericLoginCommand<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;public override IPrincipal DoAuthentication(string username, Hashtable credentials)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string password = credentials&#91;&quot;password&quot;&#93; as string;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (username == &quot;admin&quot; &amp;&amp; password == &quot;123456&quot;)<br/>&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;&nbsp;&nbsp;&nbsp;&nbsp;GenericIdentity identity = new GenericIdentity(username);<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;GenericPrincipal principal = new GenericPrincipal(identity, new string&#91;&#93; { &quot;admin&quot;, &quot;privilegeduser&quot; });<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return principal;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return null;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上面代码块，检测用户是不是属于&quot;admin&quot;和&quot;privilegeduser&quot;两个角色组之一，否则则不能通过验证。要实现授权则是通过DoAuthorization()方法来实现，我们同样可以重写实现以满足自己的需求。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除此之外还需要service-config.xml，指定通过那一个LoginCommand来执行认证与授权,以及要被授权的方法和角色组，login-command的class指向自定义的LoginCommand.<br/><br/><div class="code">&lt;security&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;security-constraint id=&quot;privileged-users&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;auth-method&gt;Login&lt;/auth-method&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;roles&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;role&gt;admin&lt;/role&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;role&gt;privilegeduser&lt;/role&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/roles&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/security-constraint&gt;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>&nbsp;&nbsp; &lt;login-command class=&quot;FlexDotNet.ServiceLibrary.Authentication.LoginCommand&quot; server=&quot;asp.net&quot;/&gt;<br/>&lt;/security&gt;</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;要使Flex能够调用认证与授权，同样需要提供一个远程服务接口，并为该接口添加RemotingServiceAttribute描述:<br/><br/><div class="code">namespace FlexDotNet.ServiceLibrary.Authentication<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// 远程服务LoginService<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class LoginService<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public LoginService()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ }<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 登录<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public bool Login(string userName,string password)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (userName == &quot;admin&quot; &amp;&amp; password == &quot;123456&quot;)<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;//do other<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<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;else<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;//do other<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 注销<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;param name=&quot;userName&quot;&gt;用户名&lt;/param&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public bool Logout(string userName)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GenericIdentity identity = new GenericIdentity(userName);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GenericPrincipal principal = new GenericPrincipal(identity, new string&#91;&#93; { &quot;admin&quot;, &quot;privilegeduser&quot; });<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (new LoginCommand().Logout(principal))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Flex或Flash端就可以通过RemoteObject来访问远程对象，Flex的访问配置如下代码块：<br/><br/><div class="code">&lt;mx:RemoteObject id=&quot;loginService&quot; destination=&quot;login&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;Login&quot; result=&quot;onLoginResult(event)&quot; fault=&quot;onLoginFault(event)&quot;/&gt;<br/>&lt;/mx:RemoteObject&gt;</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过配置RemoteObject指定访问login这个配置的远程服务，服务里配置了一远程方法Login，并分别定义了访问成功和失败的处理函数。上面的RemoteObject访问的目的地为login配置的目的地，详细配置在remoting-config.xml里，如下：<br/><br/><div class="code">&lt;destination id=&quot;login&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source&gt;FlexDotNet.ServiceLibrary.Authentication.LoginService&lt;/source&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;<br/>&lt;/destination&gt;</div><br/><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FlexDotNet.ServiceLibrary.Authentication.LoginService为自定义的一个远程服务(标记为RemotingService)接口,通过配置访问目的地，Flex远程对象组件利用此目的地通过FluorineFx网关调用远程服务接口方法。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;布局Flex界面，模拟登录验证的调用，Flex通过setCredentials（）方法请求，详细如下代码块：<br/><br/><div class="code">private function Login():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;loginService.logout();<br/>&nbsp;&nbsp;&nbsp;&nbsp;loginService.setCredentials(txtName.text,txtPassword.text);<br/>&nbsp;&nbsp;&nbsp;&nbsp;loginService.Login();<br/>}</div><br/><br/>完整的Flex端代码<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.utils.ObjectUtil;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.Alert;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function Login():void<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;loginService.logout();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loginService.setCredentials(txtName.text,txtPassword.text);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loginService.Login();<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function Logout():void<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;loginService.logout();<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onLoginResult(evt:ResultEvent):void<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;var result:Boolean = evt.result as Boolean;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(result)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alert.show(&quot;登录验证成功&quot;);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onLoginFault(evt:FaultEvent):void<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;Alert.show(ObjectUtil.toString(evt.fault),&quot;登录验证失败&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:RemoteObject id=&quot;loginService&quot; destination=&quot;login&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;Login&quot; result=&quot;onLoginResult(event)&quot; fault=&quot;onLoginFault(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:RemoteObject&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Panel x=&quot;124&quot; y=&quot;102&quot; width=&quot;250&quot; height=&quot;200&quot; layout=&quot;absolute&quot; fontSize=&quot;12&quot; title=&quot;用户登录&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;19&quot; y=&quot;28&quot; text=&quot;用户名：&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;19&quot; y=&quot;72&quot; text=&quot;密&nbsp;&nbsp; 码：&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;75&quot; y=&quot;26&quot; width=&quot;131&quot; id=&quot;txtName&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;75&quot; y=&quot;69&quot; width=&quot;131&quot; id=&quot;txtPassword&quot; displayAsPassword=&quot;true&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:HBox x=&quot;75&quot; y=&quot;107&quot; width=&quot;131&quot; height=&quot;30&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;登 录&quot; click=&quot;Login()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;清 空&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:HBox&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Panel&gt;<br/>&lt;/mx:Application&gt;</div><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a> , <a href="http://www.niuc.net/tags/authentication/" rel="tag">authentication</a> , <a href="http://www.niuc.net/tags/authorization/" rel="tag">authorization</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7875/</link>
<title><![CDATA[Flex与.NET互操作(六)：使用FluorineFx网关实现远程访问]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Mon, 03 Aug 2009 07:18:17 +0000</pubDate> 
<guid>http://www.niuc.net/post/7875/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp; 关于远程访问在本系列文章中陆续的写了不少示例了，本文没有准备深入的去探讨，为了巩固FluorineFx网关的学习和使用。于此，本文将使用FluorineFx网关来提供数据服务等多项功能来介绍通过FluorineFx实现远程访问的相关知识点。 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx提供的远程访问包括有很多方面的知道点,本文只介绍其中的三个知识点:访问远程对象返回对象,返回DataTable,返回DataSet对象.FluorineFx安装包里自带有相关的示例程序,要学习更多可直接参考这些示例程序。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 在实现访问前我们同样来做一些准备工作，建立好远程对象，如下：<br/><br/><div class="code">namespace Fluorine.ServiceLibrary<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class Book<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public int Id { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Name { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Author { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public double Price { get; set; }<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 下面是提供Flex访问的远程对象：<br/><br/><div class="code"><br/>namespace Fluorine.ServiceLibrary<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class FluorineService<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 返回一个简单对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Book GetBook()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new Book<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;Id = 1,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name = &quot;《三国演义》&quot;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Author = &quot;罗贯中&quot;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Price = 100<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 返回DataTable对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;DataTableType(&quot;Fluorine.ServiceLibrary.Book&quot;)&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public DataTable GetDataTable()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataTable dt = new DataTable(&quot;Book&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Id&quot;, typeof(int));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Name&quot;, typeof(string));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Author&quot;, typeof(string));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Price&quot;, typeof(double));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataRow dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Id&quot;&#93; = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Name&quot;&#93; = &quot;《三国演义》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Author&quot;&#93; = &quot;罗贯中&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Price&quot;&#93; = 52.30;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Id&quot;&#93; = 2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Name&quot;&#93; = &quot;《西游记》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Author&quot;&#93; = &quot;吴承恩&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Price&quot;&#93; = 39.91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return dt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// 返回DataSet对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;returns&gt;&lt;/returns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;DataSetType(&quot;Fluorine.ServiceLibrary.Book&quot;)&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public DataSet GetDataSet()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSet ds = new DataSet(&quot;DS&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataTable dt = ds.Tables.Add(&quot;Books&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Id&quot;, typeof(int));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Name&quot;, typeof(string));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Author&quot;, typeof(string));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Columns.Add(&quot;Price&quot;, typeof(double));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataRow dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Id&quot;&#93; = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Name&quot;&#93; = &quot;《三国演义》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Author&quot;&#93; = &quot;罗贯中&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Price&quot;&#93; = 52.30;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr = dt.NewRow();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Id&quot;&#93; = 2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Name&quot;&#93; = &quot;《西游记》&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Author&quot;&#93; = &quot;吴承恩&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&#91;&quot;Price&quot;&#93; = 39.91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Rows.Add(dr);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ds;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 上面代码片段中分别提供了返回一个对象，DataTable,DataSet对象的方法。这里只需要记住两个关键标识就行，它门是：DataTableType和DataSetType.&nbsp;&nbsp;下面通过Flex的非可视化组件&lt;mx:RemoteObject&gt;来访问远程对象，OK，下面我们来看看具体怎么来调用。 <br/><br/><div class="code">&lt;mx:RemoteObject id=&quot;ro&quot; destination=&quot;fluorine&quot; &gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;source=&quot;Fluorine.ServiceLibrary.FluorineService&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;fault=&quot;onFaultHandler(event)&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;GetBook&quot; result=&quot;onGetBookHandler(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;GetDataTable&quot; result=&quot;onGetDataTableHandler(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;GetDataSet&quot; result=&quot;onGetDataSetHandler(event)&quot;/&gt;<br/>&lt;/mx:RemoteObject&gt;</div><br/> <br/><br/><strong>一、返回对象示例</strong><br/><br/><div class="code">&#91;Binable&#93;<br/>private var book:BookVO;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>private function onGetBookHandler(evt:ResultEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;book=evt.result as BookVO;<br/>}</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 通过点击按扭调用远程方法GetBook()完成方法的调用，直接可以将返回结果绑定到界面元素上。<br/><br/><div class="code">&lt;mx:Button label=&quot;Book&quot; click=&quot;ro.GetBook()&quot;/&gt;<br/>&lt;mx:TextInput width=&quot;302&quot; text=&quot;{boo.Name+book.Author+book.Price}&quot;/&gt;</div><br/> <br/><br/><strong>二、返回DataTable对象</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 返回DataTable和DataSet，将结果绑定到DataGrid上显示，先看看DataGrid的定义：<br/><br/><div class="code">&lt;mx:DataGrid x=&quot;10&quot; y=&quot;10&quot; width=&quot;543&quot; height=&quot;147&quot; dataProvider=&quot;{books}&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;编号&quot; dataField=&quot;Id&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;书名&quot; dataField=&quot;Name&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;作者&quot; dataField=&quot;Author&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;价格&quot; dataField=&quot;Price&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:columns&gt;<br/>&lt;/mx:DataGrid&gt;</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; DataGrid的数据源为定义的一个ArrayCollection对象，详细如下：<br/><br/><div class="code">&#91;Binable&#93;<br/>private var books:ArrayCollection;</div><br/><br/><div class="code">private function onGetDataTableHandler(evt:ResultEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;books=evt.result as ArrayCollection;<br/>}</div><br/> <br/><br/><strong>三、返回DataTable对象</strong><br/><br/><div class="code">private function onGetDataSetHandler(evt:ResultEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;books=evt.result as ArrayCollection;<br/>}</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 如上便完成了通过FluorineFx网关来实现远程访问，下面是完整的Flex端代码，实现很简单这里就不作详细讲解：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.controls.Alert;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.collections.ArrayCollection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;Binable&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var books:ArrayCollection;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;Binable&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var book:BookVO;<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;private function onGetBookHandler(evt:ResultEvent):void<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;book=evt.result as BookVO;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onGetDataTableHandler(evt:ResultEvent):void<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;books=evt.result as ArrayCollection;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onGetDataSetHandler(evt:ResultEvent):void<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;books=evt.result as ArrayCollection;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function onFaultHandler(evt:FaultEvent):void<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;Alert.show(evt.fault.faultDetail);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Panel x=&quot;42&quot; y=&quot;56&quot; width=&quot;578&quot; height=&quot;226&quot; layout=&quot;absolute&quot; fontSize=&quot;12&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGrid x=&quot;10&quot; y=&quot;10&quot; width=&quot;543&quot; height=&quot;147&quot; dataProvider=&quot;{books}&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;编号&quot; dataField=&quot;Id&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;书名&quot; dataField=&quot;Name&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;作者&quot; dataField=&quot;Author&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;价格&quot; dataField=&quot;Price&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:DataGrid&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:ControlBar&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;DataTable&quot; click=&quot;getDataTable()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;DataSet&quot; click=&quot;getDataSet()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;Book&quot; click=&quot;ro.GetBook()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput width=&quot;302&quot; text=&quot;{boo.Name+book.Author+book.Price}&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:ControlBar&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Panel&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:RemoteObject id=&quot;ro&quot; destination=&quot;fluorine&quot; &gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;source=&quot;Fluorine.ServiceLibrary.FluorineService&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fault=&quot;onFaultHandler(event)&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;GetBook&quot; result=&quot;onGetBookHandler(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;GetDataTable&quot; result=&quot;onGetDataTableHandler(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;GetDataSet&quot; result=&quot;onGetDataSetHandler(event)&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:RemoteObject&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7874/</link>
<title><![CDATA[Flex与.NET互操作(五)：Flex和.NET协同开发利器FluorineFx及如何使用FluorineFx]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Sun, 02 Aug 2009 05:02:08 +0000</pubDate> 
<guid>http://www.niuc.net/post/7874/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp; 在本系列前面几篇文章中分别介绍了通过WebService、HTTPService、URLLoader以及FielReference等组件或类来完成Flex与.NET服务端的通信的相关知识点。通过这些方式来完成与服务端的通信是非常方便和简单的，但有他的缺点就是通信数据量较小，如要传输大量的数据或是实现不同对象的序列化传输，它们则满足不了我们的需求，需要寻找另外一种通信协议，另一种高效的传输协议来代替SOAP协议传输的方案，那便是AMF（ActionScript Message Format）协议。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 开源项目FluorineFx就是专门针对.NET平台与Flex通信提供的AMF协议通信网关，我们可以通过FluorineFx很方便的完成与.NET的通信。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx官方提供了安装包的下载和在线文档，可以帮助我们有效的利用FluorineFx来开发。 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluroineFx官方网站：http://www.fluorinefx.com/&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluroineFx下载地址：http://www.fluorinefx.com/download.html <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluroineFx在线文档：http://www.fluorinefx.com/docs/fluorine/index.html<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; OK，下面我们来看看使用FluroineFx通信的.NET和Flex配置。开发环境选择如下：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; .NET:Microsoft Visual Studio 2008 + .NET Framework 3.5<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; Flex:Adobe Flex Builder CS3 + Flex SDK 3.2<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluroineFx:FluorineFx v1.0.0.15 (<a href="http://www.fluorinefx.com/download/fluorinefx/1.0.0.15/setup.exe" target="_blank">点击可下载</a>)<br/><br/> <br/><br/> 一、.NET服务端的开发<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 通过Microsoft Visual Studio 2008 创建创建解决方案，并添加FluroineFx服务器库，如下图示：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=232" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=232" target="_blank">http://www.niuc.net/attachment.php?fid=232</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx服务库添加成功后会发现，项目模板会自动为我们创建一个Sample类和一个Echo方法，如下：<br/><br/><div class="code">namespace FlexDotNet.ServiceLibrary<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// Fluorine sample service.<br/>&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService(&quot;Fluorine sample service&quot;)&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class Sample<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Sample()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Echo(string text)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &quot;Gateway echo: &quot; + text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 接着添加FluorineFx 网站到解决方案，添加成功后网站会自动引用FluorineFx服务库的dll。如下图：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=233" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=233" target="_blank">http://www.niuc.net/attachment.php?fid=233</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 到这里我们可以简单的测试FluorineFx的.NET服务端是否成功创建。通过在浏览器中查看FluroineFx网站中的Console.aspx或是将网站设置为启动项目并设置Console.aspx为启始页运行网站都可以，程序便会运行到FluorineFx的控制台，展开左边项目的Services节点便会看到上面模板为我们创建的类和方法，点击方法节点在右边就可以进行简单的测试了，如下图示：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=234" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=234" target="_blank">http://www.niuc.net/attachment.php?fid=234</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; OK，到这里.NET的服务器端就开发完成了，这里我们需要记住几点，在接下来的Flex开发中需要根据这些参数来进行配置。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx的.NET网站目录：F:&#92;Demo&#92;FlexDotNet&#92;Web<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx的.NET网站虚拟目录：/Web<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; FluorineFx的.NET网站URL：http://localhost:2836/Web<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 接受Flex客户端请求的URL：http://localhost:2836/Web/Gateway.aspx<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 有了上面这些东西配置Flex就简单了，首先创建Flex项目，并将项目路径指向前建立的FluorineFx网站的根路径：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=235" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=235" target="_blank">http://www.niuc.net/attachment.php?fid=235</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 如上图，将Application type设置为:Web application,Application Server type设置为：<strong>ASP.NET</strong>，然后“Next”。进入下一个创建项目向导界面，将Server设置为:&quot;<strong>Use Internet Information Services (IIS)</strong>&quot;,Web Application root同样指向FluorineFx网站的根路径，Web Appliation URL则设置为上面我们获取到的路径便OK，详细见下图：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=236" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=236" target="_blank">http://www.niuc.net/attachment.php?fid=236</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 按照上面步骤配置好后通过点击“<strong>Validate Configuration</strong>”进行配置验证，如过验证结果是： <strong>The web application root and the URL are valid</strong>.则代表配置正确，可以直接点下一步只到完成项目的创建。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; Flex项目创建完毕，下面在通过一些相应的配置就可以通过FluorineFx和.NET通信了。开发项目属性设置面板，设置其Flex Compiler为下图所示（-services的配置也可以设置为相对路径）：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=237" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=237" target="_blank">http://www.niuc.net/attachment.php?fid=237</a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 设置Flex Server为如下配置，可以点“Validate Location”验证设置的正确性：<br/>[img]attachment.php?fid=238<br/>&nbsp;&nbsp;&nbsp;&nbsp; 最后设置输出路径就完成了Flex端的配置了：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=239" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=239" target="_blank">http://www.niuc.net/attachment.php?fid=239</a><br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 到这里Flex端的配置就全部完成，下面我们通过FluorineFx库模板为我们生成的Sample为例来测试下该环境是否可以通过，在Flex的mxml文件下通过&lt;mx:RemoteObject&gt;标签来访问远程对象，详细如下：<br/><br/><div class="code">&lt;mx:RemoteObject id=&quot;service&quot; destination=&quot;fluorine&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;source=&quot;FlexDotNet.ServiceLibrary.Sample&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;Echo&quot; result=&quot;onResult(event)&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:method&gt;<br/>&lt;/mx:RemoteObject&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 这里需要注意的是destination需要设置为与remoting-config.xml中的destination的id一致，source则配置为远程对象的全路径（名称空间＋类），通过&lt;mx:method&gt;标签配置远程对象下的方法并设置其成功调用后的结果处理函数，下面便可通过id去调用远程方法了。<br/><br/><div class="code">&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onClick():void<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.Echo(txtInput.text);<br/>&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;internal function onResult(evt:ResultEvent):void<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txtResult.text = evt.result.toString();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&lt;/mx:Script&gt; </div><br/><br/>下面是完整的Flex客户端mxml的代码定义：<br/><br/>完整的示例代码<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:RemoteObject id=&quot;service&quot; destination=&quot;fluorine&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;source=&quot;FlexDotNet.ServiceLibrary.Sample&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;Echo&quot; result=&quot;onResult(event)&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:method&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:RemoteObject&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onClick():void<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;service.Echo(txtInput.text);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onResult(evt:ResultEvent):void<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;txtResult.text = evt.result.toString();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Panel x=&quot;53&quot; y=&quot;52&quot; width=&quot;250&quot; height=&quot;200&quot; layout=&quot;absolute&quot; title=&quot;测试FluorineFx&quot; fontSize=&quot;12&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;35&quot; y=&quot;21&quot; id=&quot;txtInput&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;35&quot; y=&quot;63&quot; label=&quot;确 定&quot; fontWeight=&quot;normal&quot; click=&quot;onClick()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;35&quot; y=&quot;95&quot; text=&quot;结 果：&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;35&quot; y=&quot;123&quot; width=&quot;160&quot; id=&quot;txtResult&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Panel&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/>本文示例截图：<br/><br/><img src="http://www.niuc.net/template/EleganX2/images/viewimage.gif" alt=""/><a href="http://www.niuc.net/attachment.php?fid=240" target="_blank">点击在新窗口中浏览此图片</a><br/><a href="http://www.niuc.net/attachment.php?fid=240" target="_blank">http://www.niuc.net/attachment.php?fid=240</a><br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; Flex中的远程对象访问，也就是服务端提供一个远程服务对象（RemotingService Object），在Flex客户端通过相应的访问技术去调用远程对象的过程。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 在本系列文章的前面几篇文章中所介绍的访问Webservice的方法，也就是一种远程对象方法，只不过他是基于WEB服务（WebServie）的远程访问，不是基于远程对象（Remoting Object）的的远程访问。要想直接实现基于对象的远程访问是比较麻烦的，然后FluorineFx则专门为我们提供了该功能，通过FluorineFx的核心库来开发远程对象（Remoting Object）服务，具体是怎么实现的呢？FluorineFx要求为远程对象提供[RemotingService]标记来提供远程对象服务，看看下面的RemotingServiceAttribute的详细定义：<br/><br/><div class="code">&#91;AttributeUsage(AttributeTargets.Class, AllowMultiple = false)&#93;<br/>public sealed class RemotingServiceAttribute : Attribute<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;public RemotingServiceAttribute();<br/>&nbsp;&nbsp;&nbsp;&nbsp;public RemotingServiceAttribute(string serviceName);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 从上一篇文章中的示例代码可以看出，使用.NET（c#）定义了一个Sample的远程对象服务类，并为其指定了[RemotingService]，详细如下： <br/><br/><div class="code">&nbsp;&nbsp;&nbsp;&nbsp;&#91;RemotingService(&quot;Fluorine sample service&quot;)&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public class Sample<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Sample()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Echo(string text)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &quot;Gateway echo: &quot; + text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 以上搭建FluorineFx与.NET的开发环境过程已经完成，下面介绍Flex客户端调用FluorineFx的远程对象示例，我们在来看看这个示例：<br/><br/><div class="code">&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:RemoteObject id=&quot;service&quot; destination=&quot;fluorine&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;source=&quot;FlexDotNet.ServiceLibrary.Sample&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:method name=&quot;Echo&quot; result=&quot;onResult(event)&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:method&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:RemoteObject&gt;</div><br/><br/><div class="code">&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onClick():void<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;service.Echo(txtInput.text);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onResult(evt:ResultEvent):void<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;txtResult.text = evt.result.toString();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 如上可实现远程对象访问，通过Flex的非可视化组件&lt;mx:RemoteObject&gt;进行远程对象连接。其中的source属性指定远程对象，格式为全限定名（命名空间+类名）。destination属性是非常重要的，这决定了Flex客户端是否可以正确的访问到远对象，相关配置如下：<br/><br/><div class="code">&nbsp;&nbsp;&nbsp;&nbsp;&lt;destination id=&quot;fluorine&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source&gt;*&lt;/source&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/destination&gt;</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 在&lt;mx:RemoteObject&gt;组件内部使用&lt;mx:Mothod&gt;组件配置远程对象中的方法，详细见本文前面部分。要真实实现远程对象访问的核心是对象的适配器和连接通道：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br/>&lt;service id=&quot;remoting-service&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;class=&quot;flex.messaging.services.RemotingService&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;messageTypes=&quot;flex.messaging.messages.RemotingMessage&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;adapters&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;adapter-definition id=&quot;dotnet&quot; class=&quot;FluorineFx.Remoting.RemotingAdapter&quot; default=&quot;true&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/adapters&gt;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;default-channels&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;channel ref=&quot;my-amf&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/default-channels&gt;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;destination id=&quot;fluorine&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source&gt;*&lt;/source&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/destination&gt;<br/>&lt;/service&gt;</div><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 实际开发中我们可以进行自定义通信通道，默认情况下是使用FluorineFx为我们提供的默认连接通道：<br/><br/><div class="code">&nbsp;&nbsp;&nbsp;&nbsp;&lt;channels&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;channel-definition id=&quot;my-amf&quot; class=&quot;mx.messaging.channels.AMFChannel&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;endpoint uri=&quot;http://{server.name}:{server.port}/{context.root}/Gateway.aspx&quot; class=&quot;flex.messaging.endpoints.AMFEndpoint&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- &lt;legacy-collection&gt;true&lt;/legacy-collection&gt; --&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/channel-definition&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/channels&gt;</div><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/fluorinefx/" rel="tag">fluorinefx</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7873/</link>
<title><![CDATA[Flex与.NET互操作(四)：使用FileReference+HttpHandler实现文件上传/下载]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Sat, 01 Aug 2009 03:38:56 +0000</pubDate> 
<guid>http://www.niuc.net/post/7873/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp; 在Flex的应用开发中，同ASP.NET,JSP,PHP等应用一样，都会有上传/下载文件的应用需求，Flex的SDK也为我们提供了专门的类FileRefUdderence实现文件上传/下载 。Flex只是作为一个客户端，要实现上传或下载必须得为其提供一个服务端来接受上传或下载的请求，本文以ASP.NET中的HttpHandler作为文件上传的服务端来完成上传功能。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; OK，我们从Flex客户端开始，看看客户端是通过什么方式想服务端发起请求。Flex客户端要完成文件上传下载都是通过FileRefUdderence来实现，首先得定义一个该类型对象实例：<br/><br/><div class="code">&#91;Bindable&#93;<br/>private var stateText:String = &quot;请选择一个文件上传&quot;;<br/>//通过调用file对象的方法来完成上传和下载功能<br/>private var file:FileReference = new FileReference();</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 上传文件通常涉及到的有选择文件、上传文件以及上传完成这些最基本的处理过程。OK，下面我们就以这三个过程为例来看看Flex是怎么来完成文件的上传功能。首先为这三个功能点分别添加监听事件处理函数，在程序加载时调用：<br/><br/><div class="code">internal function initApp():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.SELECT,onSelected);<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.COMPLETE,onCompleted);<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(ProgressEvent.PROGRESS,onProgress);<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 另外我们也可以不用上面这中定义一个函数在程序加载时调用进行初始化操作，应用程序(mxml)的初始化操作又creationComplete方法完成，另外还有一个比它先执行的方法createChildren(),我们可以直接在mxml下重写该方法来实现应用程序的初始化，如下：<br/><br/><div class="code">/**<br/> * createChildren 比 creationComplete 事件更早发生<br/> * */<br/>protected override function createChildren():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.SELECT,onSelected);<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.COMPLETE,onCompleted);<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(ProgressEvent.PROGRESS,onProgress);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 这三个事件处理函数的详细定义如下（其中的stateText为String的变量，用于显示文件上传状态提示）：<br/><br/><div class="code">internal function onSelected(evt:Event):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;stateText = &quot;选择了文件&quot; + file.name;<br/>}<br/><br/>internal function onCompleted(evt:Event):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;stateText = &quot;上传完毕！&quot;;<br/>}<br/><br/>internal function onProgress(evt:ProgressEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;stateText = &quot;已上传 &quot; + Math.round(100 * evt.bytesLoaded / evt.bytesTotal) + &quot;%&quot;;<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 到这里客户端就只差一步了，那就是完成发起上传请求的方法，实际上就是通过URLRequest对象创建一个与服务端的连接，然后直接调用FielReference类的upload()方法就可完成该功能，详细如下代码定义：<br/><br/><div class="code">/**<br/> * 调用FileReference的实例方法upload()实现文件上传<br/> * */<br/>internal function onUpLoad():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(file.size &gt; 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stateText = &quot;正在上传文件：&quot; + file.name;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;var request:URLRequest = new URLRequest();<br/>&nbsp;&nbsp;&nbsp;&nbsp;request.url=&quot;http://localhost/Web/UpLoadHandler.ashx&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.upload(request);<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 写好了upload方法，现在就是调用他了，通过按扭的click事件直接调用就可以，另外调用file.browse()方法则实现选择文件的功能，如下mxml代码描述：<br/><br/><div class="code">&lt;mx:TextInput x=&quot;10&quot; y=&quot;57&quot; id=&quot;txtFile&quot; text=&quot;{stateText}&quot; width=&quot;229&quot;/&gt;<br/>&lt;mx:Button x=&quot;247&quot; y=&quot;57&quot; label=&quot;选择&quot; fontWeight=&quot;normal&quot; click=&quot;{file.browse()}&quot;/&gt;<br/>&lt;mx:Button x=&quot;29&quot; y=&quot;111&quot; label=&quot;上传文件&quot; width=&quot;111&quot; fontWeight=&quot;normal&quot; click=&quot;onUpLoad()&quot;/&gt;</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 如上便完成了上传文件的Flex客户端开发，通过file.upload()方法，将把选择的文件通过二进制的形式发送到指定的服务端，并自动传递一个叫“fileName”的参数，服务端通过fileName便可以接收到客户端请求上传的文件。最后我们来看看服务端的UpLoadHandler.ashx的详细定义：<br/><br/><div class="code">public class UpLoadHandler : IHttpHandler<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//文件上传目录<br/>&nbsp;&nbsp;&nbsp;&nbsp;private string uploadFolder = &quot;UpLoad&quot;;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;public void ProcessRequest(HttpContext context)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.ContentType = &quot;text/plain&quot;;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpFileCollection files = context.Request.Files;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (files.Count &gt; 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string path = context.Server.MapPath(uploadFolder);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpPostedFile file = files&#91;0&#93;;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (file != null &amp;&amp; file.ContentLength &gt; 0)<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;string savePath = path + &quot;/&quot; + context.Request.Form&#91;&quot;fileName&quot;&#93;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.SaveAs(savePath);<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;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(&quot;参数错误&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.End();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;public bool IsReusable<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>}</div><br/>&nbsp;&nbsp;&nbsp;&nbsp; 如上一系列的步骤便可完成上传文件的功能，下面便是上传文件示例程序运行截图：<br/><a href="http://www.niuc.net/attachment.php?fid=230" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=230" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 实现了文件上传下面来看看怎么实现文件下载， 以上面上传示例中上传的mp3为例，下面我们来看看怎么从服务器（http://localhost/Web/UpLoad/做你的爱人.mp3）上完成文件（做你的爱人.mp3）的下载。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 要实现文件下载对服务器端只要保证被下载文件存在就OK，同上传文件一样需要实例化一个FielReference对象的实例，并为其添加相应的事件处理函数：<br/><br/><div class="code">private var fileDown:FileReference = new FileReference();</div><br/><br/><div class="code">/**<br/> * createChildren 比 creationComplete 事件更早发生<br/> * */<br/>protected override function createChildren():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;super.createChildren();<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.SELECT,onSelected);<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.COMPLETE,onCompleted);<br/>&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(ProgressEvent.PROGRESS,onProgress);<br/>&nbsp;&nbsp;&nbsp;&nbsp;//实现文件下载<br/>&nbsp;&nbsp;&nbsp;&nbsp;fileDown.addEventListener(Event.COMPLETE,onDownCompleted);<br/>&nbsp;&nbsp;&nbsp;&nbsp;fileDown.addEventListener(ProgressEvent.PROGRESS,onDownProgress);<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 如上为实现下载文件的实例fileDown注册了成功下载文件后事件处理函数和下载过程处理函数，下面是两个方法的详细定义：<br/><br/><div class="code">internal function onDownCompleted(evt:Event):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var fileRef:FileReference = evt.currentTarget as FileReference;<br/>&nbsp;&nbsp;&nbsp;&nbsp;resultLabel.text = &quot;文件名：&quot; + fileRef.name + &quot;下载完毕！&quot;;<br/>}<br/><br/>internal function onDownProgress(evt:ProgressEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;downState.text = &quot;已下载： &quot; + Math.round(100 * evt.bytesLoaded / evt.bytesTotal) + &quot;%&quot;;<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 完成了对象事件的开发，最后便上惩罚下载请求了，直接调用FileReference类所提供的download()方法既可：<br/><br/><div class="code">/**<br/> * 调用FileReference类的实例方法download()实现文件下载<br/> * */<br/>internal function onDownLoad():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var request:URLRequest = new URLRequest();<br/>&nbsp;&nbsp;&nbsp;&nbsp;request.url=&quot;http://localhost:1146/UpLoad/做你的爱人.mp3&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;fileDown.download(request);<br/>} </div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 程序执行到download（）方法的时候会自动弹出选择保存文件对话框，根据实际情况选择好保存路径就OK。下面是实现上传和下载的完整代码：<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Panel x=&quot;49&quot; y=&quot;66&quot; width=&quot;551&quot; height=&quot;164&quot; layout=&quot;absolute&quot; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title=&quot;使用FileReference上传/下载文件&quot; fontSize=&quot;12&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:HDividedBox x=&quot;10&quot; y=&quot;10&quot; width=&quot;511&quot; height=&quot;102&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Canvas&nbsp;&nbsp;id=&quot;left&quot; backgroundColor=&quot;#D7F4FF&quot; height=&quot;100%&quot; width=&quot;209&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;4&quot; y=&quot;20&quot; id=&quot;txtFile&quot; text=&quot;{stateText}&quot; width=&quot;135&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;147&quot; y=&quot;20&quot; label=&quot;选择&quot; fontWeight=&quot;normal&quot; click=&quot;{file.browse()}&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;31&quot; y=&quot;68&quot; label=&quot;上传文件&quot; width=&quot;111&quot; fontWeight=&quot;normal&quot; click=&quot;onUpLoad()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Canvas&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Canvas id=&quot;right&quot; backgroundColor=&quot;#D7F4FF&quot; height=&quot;100%&quot; width=&quot;282&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;6&quot; y=&quot;9&quot; text=&quot;http://localhost/Web/UpLoad/做你的爱人.mp3&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button x=&quot;10&quot; y=&quot;37&quot; label=&quot;下载文件&quot; fontWeight=&quot;normal&quot; click=&quot;onDownLoad()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Label x=&quot;10&quot; y=&quot;74&quot; width=&quot;272&quot; id=&quot;resultLabel&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:TextInput x=&quot;122&quot; y=&quot;37&quot; id=&quot;downState&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Canvas&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:HDividedBox&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Panel&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;Bindable&#93;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var stateText:String = &quot;请选择一个文件上传&quot;;<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;private var file:FileReference = new FileReference();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private var fileDown:FileReference = new FileReference();<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;/**<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * createChildren 比 creationComplete 事件更早发生<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;protected override function createChildren():void<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;super.createChildren();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.SELECT,onSelected);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.COMPLETE,onCompleted);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(ProgressEvent.PROGRESS,onProgress);<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;fileDown.addEventListener(Event.COMPLETE,onDownCompleted);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileDown.addEventListener(ProgressEvent.PROGRESS,onDownProgress);<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;<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function initApp():void<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;file.addEventListener(Event.SELECT,onSelected);<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(Event.COMPLETE,onCompleted);<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.addEventListener(ProgressEvent.PROGRESS,onProgress);<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onSelected(evt:Event):void<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;stateText = &quot;选择了文件:&quot; + file.name;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onCompleted(evt:Event):void<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;stateText = &quot;上传完毕！&quot;;<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;<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;internal function onDownCompleted(evt:Event):void<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;var fileRef:FileReference = evt.currentTarget as FileReference;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultLabel.text = &quot;文件名：&quot; + fileRef.name + &quot;下载完毕！&quot;;<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onProgress(evt:ProgressEvent):void<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;stateText = &quot;已上传： &quot; + Math.round(100 * evt.bytesLoaded / evt.bytesTotal) + &quot;%&quot;;<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;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onDownProgress(evt:ProgressEvent):void<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;downState.text = &quot;已下载： &quot; + Math.round(100 * evt.bytesLoaded / evt.bytesTotal) + &quot;%&quot;;<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;<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; * 调用FileReference的实例方法upload()实现文件上传<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;internal function onUpLoad():void<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;if(file.size &gt; 0)<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;stateText = &quot;正在上传文件：&quot; + file.name;<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;var request:URLRequest = new URLRequest();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.url=http://localhost/Web/UpLoadHandler.ashx;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.upload(request);<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;<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; * 调用FileReference类的实例方法download()实现文件下载<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;internal function onDownLoad():void<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;var request:URLRequest = new URLRequest();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.url=&quot;http://localhost/Web/UpLoad/做你的爱人.mp3&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileDown.download(request);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/>&lt;/mx:Application&gt;</div><br/>实现上传和下载的完整代码<br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 程序运行截图：<br/><a href="http://www.niuc.net/attachment.php?fid=231" target="_blank"><img src="http://www.niuc.net/attachment.php?fid=231" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>Tags - <a href="http://www.niuc.net/tags/c%2523%25E5%25BC%2580%25E5%258F%2591%25E6%258A%2580%25E6%259C%25AF/" rel="tag">c#开发技术</a> , <a href="http://www.niuc.net/tags/flash%25E6%258A%2580%25E6%259C%25AF/" rel="tag">flash技术</a> , <a href="http://www.niuc.net/tags/filereference/" rel="tag">filereference</a> , <a href="http://www.niuc.net/tags/httphandler/" rel="tag">httphandler</a>
]]>
</description>
</item><item>
<link>http://www.niuc.net/post/7872/</link>
<title><![CDATA[Flex与.NET互操作(三)：使用HttpService、URLReqeust和URLLoader加载/传输数据]]></title> 
<author>gdgzboy &lt;admin@niuc.net&gt;</author>
<category><![CDATA[RIA技术]]></category>
<pubDate>Fri, 31 Jul 2009 04:38:00 +0000</pubDate> 
<guid>http://www.niuc.net/post/7872/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp; 在前两篇文章中分别介绍了Flex与.NET的WebService之间的数据交互通信知识，本文将介绍另外一种加载数据以及发起请求的方式。ActionScript 3.0中提供的数据加载请求类主要是HTTPService,URLLoader和URLRequest，可以通过他们协同来完成数据加载和请求。下面我么便来看看这三个类是怎么来完成数据加载工作。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 在本地IIS服务器上有如下定义的XML文件：<br/><br/><div class="code"><br/>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;<br/>&lt;Root&gt;<br/>&nbsp;&nbsp;&lt;Book&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Id&gt;1&lt;/Id&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Name&gt;《三国演义》&lt;/Name&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Author&gt;罗贯中&lt;/Author&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Price&gt;52.30&lt;/Price&gt;<br/>&nbsp;&nbsp;&lt;/Book&gt;<br/>&nbsp;&nbsp;&lt;Book&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Id&gt;2&lt;/Id&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Name&gt;《西游记》&lt;/Name&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Author&gt;吴承恩&lt;/Author&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Price&gt;39.91&lt;/Price&gt;<br/>&nbsp;&nbsp;&lt;/Book&gt;<br/>&nbsp;&nbsp;&lt;Book&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Id&gt;3&lt;/Id&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Name&gt;《红楼梦》&lt;/Name&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Author&gt;曹雪芹&lt;/Author&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Price&gt;48.20&lt;/Price&gt;<br/>&nbsp;&nbsp;&lt;/Book&gt;<br/>&nbsp;&nbsp;&lt;Book&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Id&gt;4&lt;/Id&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Name&gt;《水浒传》&lt;/Name&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Author&gt;施耐庵&lt;/Author&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Price&gt;39.85&lt;/Price&gt;<br/>&nbsp;&nbsp;&lt;/Book&gt;<br/>&lt;/Root&gt;</div><br/><br/><br/><strong>一、使用HTTPService传递和加载数据</strong><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 使用HTTPService可以实现加载数据，也可以实现参数传递，下面通过两个示例程序来讲解这两个知识点。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 首先来看看HTTPService加载数据的方式。在Flex中使用HTTPService来装载外部数据是非常简单的，他是基于HTTP协议发送POST和GET请求外部数据,然后通过指定的监听方法来处理响应。我们可以通过<mx:HTTPService>标签来完成对数据源的连接，也可以通过可编程方式来处理,两种方式没什么大的差距，实际开发中可以根据自己喜好选择。 <br/><br/><div class="code"><br/>internal function onClick():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var service:HTTPService = new HTTPService();<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.url = &quot;http://localhost:1146/Data/Book.xml&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.useProxy = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.resultFormat=&quot;e4x&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.addEventListener(ResultEvent.RESULT,onResultHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.send();<br/>}<br/><br/>internal function onResultHandler(evt:ResultEvent):void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var xml:XML = evt.result as XML;<br/>&nbsp;&nbsp;&nbsp;&nbsp;trace(xml);<br/>&nbsp;&nbsp;&nbsp;&nbsp;bookGrid.dataProvider = xml.Book;<br/>}</div><br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp; 该示例的运行结果见文章最后，下面是这个示例的完整代码：<br/><br/>完整示例代码<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.http.HTTPService;<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;internal function onClick():void<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;var service:HTTPService = new HTTPService();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.url = &quot;http://localhost:1146/Data/Book.xml&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.useProxy = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.resultFormat=&quot;e4x&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.addEventListener(ResultEvent.RESULT,onResultHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.send();<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;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;internal function onResultHandler(evt:ResultEvent):void<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;var xml:XML = evt.result as XML;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trace(xml);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bookGrid.dataProvider = xml.Book;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;&#93;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Script&gt;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Panel x=&quot;49.5&quot; y=&quot;94&quot; width=&quot;419&quot; height=&quot;267&quot; layout=&quot;absolute&quot; fontSize=&quot;12&quot; title=&quot;使用HTTPService加载XML数据&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGrid x=&quot;10&quot; y=&quot;10&quot; width=&quot;377&quot; id=&quot;bookGrid&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;编号&quot; dataField=&quot;Id&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;书名&quot; dataField=&quot;Name&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;作者&quot; dataField=&quot;Author&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:DataGridColumn headerText=&quot;价格&quot; dataField=&quot;Price&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:columns&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:DataGrid&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:ControlBar height=&quot;42&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Button label=&quot;加载数据&quot; fontWeight=&quot;normal&quot; click=&quot;onClick()&quot;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:ControlBar&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mx:Panel&gt;<br/>&lt;/mx:Application&gt;</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; OK，我们来看看使用HTTPService传递参数到服务端是怎么实现的。使用HTTPService传递参数可以通过两种方式实现，分别如下：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 1、直接在请求URL后面跟上参数列表，如：http://localhost/web/Test.aspx?a=1&b=2。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 2、通过Flex SDK为我们提供专门用语参数传递的对象（URLVariables）来实现。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 下面以一道简单的加法运算来演示HTTPService传递参数的使用，在Flex里将需要进行加法运算的两个数传递到.NET服务端并计算其和后返回给Flex客户端，两种方式传递没有太大的区别，详细请看如下代码演示：<br/><br/><div class="code"><br/>/**<br/> * 通过RUL参数直接传递<br/> * */<br/>internal function onClick():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var service:HTTPService = new HTTPService();<br/>&nbsp;&nbsp;&nbsp;&nbsp;var a:String = txtA.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;var b:String = txtB.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.url = &quot;http://localhost:1146/OperationHandler.ashx?a=&quot;+a+&quot;&amp;b=&quot;+b;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.useProxy = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.resultFormat=&quot;e4x&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.addEventListener(ResultEvent.RESULT,onResultHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.send();<br/>}<br/><br/>/**<br/> * 通过URLVariables进行参数传递<br/> * */<br/>internal function onClick():void<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;var service:HTTPService = new HTTPService();<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.url = &quot;http://localhost:1146/OperationHandler.ashx&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.useProxy = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.resultFormat=&quot;e4x&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.addEventListener(ResultEvent.RESULT,onResultHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;var param:URLVariables = new URLVariables();<br/>&nbsp;&nbsp;&nbsp;&nbsp;param.a = txtA.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;param.b = txtB.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;service.send();<br/>}</div><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是完整的示例代码，可以把onClick()方法相互切换来测试两种不同的参数传递方式。<br/><br/>完整的示例代码<br/><br/><div class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br/>&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mx:Script&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!&#91;CDATA&#91;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.FaultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.events.ResultEvent;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import mx.rpc.http.HTTPService;<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;/**<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 通过RUL参数直接传递<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;internal function onClick():void<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;var service:HTTPService = new HTTPService();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var a:String = txtA.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var b:String = txtB.text;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.url = &quot;http://localhost:1146/OperationHandler.ashx?a=&quot;+a+&quot;&amp;b=&quot;+b;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.useProxy = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.resultFormat=&quot;e4x&quot;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.addEventListener(ResultEvent.RESULT,onResultHandler);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.send();<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;<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; * 通过URLVariables进行参数传递<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;internal function onClick():void<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;var service:HTTPService = new HTTPService();<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.url = &quot;http://localhost:1146/OperationHandler.ashx&quot;;<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.useProxy = false;<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.resultFormat=&quot;e4x&quot;;<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.addEventListener(ResultEvent.RESULT,onResultHandler);<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var param:URLVariables = new URLVariables();<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;param.a = txtA.t