﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-eXile 的专栏-随笔分类-网络开发</title><link>http://www.cppblog.com/eXile/category/7026.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 13 Jan 2010 01:32:47 GMT</lastBuildDate><pubDate>Wed, 13 Jan 2010 01:32:47 GMT</pubDate><ttl>60</ttl><item><title>好玩的Go语言</title><link>http://www.cppblog.com/eXile/archive/2010/01/11/105422.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Mon, 11 Jan 2010 11:48:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2010/01/11/105422.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/105422.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2010/01/11/105422.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/105422.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/105422.html</trackback:ping><description><![CDATA[
<span style="FONT-WEIGHT: bold">&nbsp;&nbsp;&nbsp;&nbsp; 1.什么是Go语言</span><br><br>&nbsp;&nbsp;&nbsp; Go语言是Google推出的新的一个致力于系统级的编程语言。很多人说它是 C + Python，既有c的灵活高效，又有Python的简单易用，它的原则是 Simple &amp;&amp; Fast。它的语法规则很简单。其官方网站上有一个《三天学会Go语言》的教程，包括三部分：基本结构，面向对象，并发。一个周末的时间就差不多可以掌握其基本面貌。相对来说，第三部分&#8220;并发&#8221;似乎难接受一些。但是如果你对多线程，同步，消息队列这些东西很有经验的话，对它的概念也会容易理解。<br><br style="FONT-WEIGHT: bold"><span style="FONT-WEIGHT: bold">&nbsp;&nbsp;&nbsp;&nbsp; 2.Go语言的面向对象</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp; Go语言在C语言语法的基础上，以最简洁的形式加入了面向对象。<br>&nbsp;&nbsp;&nbsp; 关于继承：Go语言没有继承。但是它支持嵌入，这个有点类似于其它语言的mixin，可以用来模拟继承。<br>&nbsp;&nbsp;&nbsp; 关于多态：Go 语言的最大特点是它的接口定义。所谓&#8220;接口&#8221;，就是一组方法的集合。任何一个类只要实现了一个接口的所有方法，则是该接口的实现者，不需要显式声明实现该接口。所以一个没有任何方法的空接口可以代表任何类型。<br style="FONT-WEIGHT: bold">&nbsp;&nbsp;&nbsp; <br>&nbsp; &nbsp;&nbsp; <span style="FONT-WEIGHT: bold">3.Go语言的并发</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp; Go语言提出一个新的概念—Go例程，有点类似于线程，但是更加轻量，更省资源。Go例程之间的通信方式 ——信道，这是GO 语言的核心概念，有点类似于UNIX的Pipe。在Go语言中，不需要接触线程，锁这些低阶概念。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="FONT-WEIGHT: bold"> 4.Go语言可以用来做什么</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp; Go语言目前最强的是它的网络功能。它的package中已经实现了最常见的网络协议和编码处理。Go的官方网站使用的就是Go语言，实际上它就是Go的文档系统godoc。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还没有官方对数据库支持，不过因为通过某种办法可以在Go语言中直接调用C函数，所以很容易的实现对MYSQL 或者 Sqlite 这些数据库的支持。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至于GUI，这估计目前还不在设计者的考虑范围之内，因为他们连Windows都不舍得支持。不过可以通过它的http包和template包等等，已经构成了一个WEB框架，可以用来实现WEB GUI的开发，使用Go写一个带有路径分派的Http服务器也就几行代码的事。<br>&nbsp;&nbsp;&nbsp;&nbsp; <br><br><br><img src ="http://www.cppblog.com/eXile/aggbug/105422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2010-01-11 19:48 <a href="http://www.cppblog.com/eXile/archive/2010/01/11/105422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[T] ICE实例学习：Let's Chat!  (2) 实现服务器</title><link>http://www.cppblog.com/eXile/archive/2009/03/26/77897.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Wed, 25 Mar 2009 16:54:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2009/03/26/77897.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/77897.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2009/03/26/77897.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/77897.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/77897.html</trackback:ping><description><![CDATA[<br><span style="FONT-SIZE: 18pt"><strong>服务器实现：</strong></span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务器使用C++。注意它的结构：类 ChatRoom 实现了大部分的应用逻辑。为了支持推模型与拉模型，服务器实现了类ChatSession 和类 PollingChatSession。 ChatRoom 调用 ChatRoomCallbackAdapter 对象的 send 函数来传递客户消息，该对象隐藏了两种模型之间的差异。<br><br>ChatRoom 实现：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ChatRoom是一个普通的C++对象，而不是一个Servant.<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;C++&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackAdapter&nbsp;{&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000">&nbsp;};&nbsp;<br>typedef&nbsp;IceUtil::Handle</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ChatRoomCallbackAdapter</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackAdapterPtr;&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ChatRoom&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;IceUtil::Shared&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;reserve(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;unreserve(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;join(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackAdapterPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;leave(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Ice::Long&nbsp;send(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;map</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">,&nbsp;ChatRoomCallbackAdapterPtr</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackMap;&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ChatRoomCallbackMap&nbsp;_members;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;_reserved;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex&nbsp;_mutex;&nbsp;<br>};&nbsp;<br>typedef&nbsp;IceUtil::Handle</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ChatRoom</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;ChatRoomPtr;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 成员_reserverd是一个字符串集合，它存储已经建立回话，但是还没有加入聊天室的客户名。_members存储当前聊天室的所有用户（已经调用过join函数的用户）。<br><br>&nbsp;&nbsp;&nbsp;&nbsp; 成员函数 reserve 和 unreserve 维护 _reserved 集合。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;C++&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;<br>ChatRoom::reserve(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;name)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_reserved.find(name)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;_reserved.end()&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;_members.find(name)&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;_members.end())&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">The&nbsp;name&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;name&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;is&nbsp;already&nbsp;in&nbsp;use.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_reserved.insert(name);&nbsp;<br>}&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;<br>ChatRoom::unreserve(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;name)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_reserved.erase(name);&nbsp;<br>}</span></div>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp; join操作添加用户到聊天室。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;C++&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;<br>ChatRoom::join(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;name,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackAdapterPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;callback)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Int64&nbsp;timestamp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;IceUtil::Time::now().toMilliSeconds();&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_reserved.erase(name);&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Ice::StringSeq&nbsp;names;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ChatRoomCallbackMap::const_iterator&nbsp;q;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(q&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_members.begin();&nbsp;q&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;_members.end();&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">q)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;names.push_back((</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">q).first);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;callback</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">init(names);&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_members[name]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;callback;&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;UserJoinedEventPtr&nbsp;e&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;UserJoinedEvent(timestamp,&nbsp;name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(q&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_members.begin();&nbsp;q&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;_members.end();&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">q)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">second</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">join(e);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>}<br></span></div>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send实现，同join实现非常类似：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;C++&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Ice::Long&nbsp;<br>ChatRoom::send(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;name,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;message)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Int64&nbsp;timestamp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;IceUtil::Time::now().toMilliSeconds();&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;MessageEventPtr&nbsp;e&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;MessageEvent(timestamp,&nbsp;name,&nbsp;message);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(ChatRoomCallbackMap::iterator&nbsp;q&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_members.begin();&nbsp;q&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;_members.end();&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">q)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">second</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">send(e);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;timestamp;&nbsp;<br>}</span></div>
<p>&nbsp;</p>
<p>&nbsp;类 ChatRoomCallbackAdapter<br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;C++&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackAdapter&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;IceUtil::Shared&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;init(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::StringSeq</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;join(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;UserJoinedEventPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;leave(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;UserLeftEventPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;send(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;MessageEventPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br>};</span></div>
<br>推模式 CallbackAdapter 实现：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;SessionCallbackAdapter&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackAdapter&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;SessionCallbackAdapter(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackPrx</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;callback,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatSessionPrx</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;session)&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;_callback(callback),&nbsp;_session(session)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;init(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::StringSeq</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;users)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_callback</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">init_async(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AMICallback</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">AMI_ChatRoomCallback_init</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(_session),&nbsp;users);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;join(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;UserJoinedEventPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;e)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_callback</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">join_async(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AMICallback</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">AMI_ChatRoomCallback_join</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(_session),&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">timestamp,&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;leave(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;UserLeftEventPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;e)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_callback</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">leave_async(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AMICallback</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">AMI_ChatRoomCallback_leave</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(_session),&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">timestamp,&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;send(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;MessageEventPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;e)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_callback</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">send_async(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AMICallback</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">AMI_ChatRoomCallback_send</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(_session),&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">timestamp,&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">name,&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;e</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">message);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackPrx&nbsp;_callback;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatSessionPrx&nbsp;_session;&nbsp;<br>};<br></span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看一下SessionCallbackAdapter的四个成员函数，当异步调用完成时，都使用类AMICallback来接收通知。它的定义如下：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;AMICallback&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;T&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;AMICallback(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatSessionPrx</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;session)&nbsp;:&nbsp;_session(session)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ice_response()&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ice_exception(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Exception</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_session</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">destroy();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Collocated&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::LocalException</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatSessionPrx&nbsp;_session;&nbsp;<br>};<br></span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当用户回调操作抛出异常，服务器立即销毁客户会话，即把该用户赶出聊天室。这是因为，一旦客户的回调对象出现了一次异常，它以后也就不可能再正常。<br><br><br><span style="FONT-SIZE: 14pt">推模式会话创建</span>：<br><br>&nbsp;&nbsp;&nbsp;&nbsp; 现在来看一下会话创建。推模式的客户使用Glacier2，所以要使用Glacier2的会话创建机制。Glacier2 允许用户通过提供一个Glacier2::SessionManager对象的代理来自定义会话创建机制。通过设置Glacier2.SessionManager属性来配置Gloacier2，就可以使用自己的会话管理器。会话管理器除了一个trivial构造函数（设置聊天室指针），只有一个操作，create，Glacier2调用它来代理应用的会话创建。 create 操作必须返回一个会话代理（类型为Glacier2::Session*）。实现如下：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Glacier2::SessionPrx&nbsp;<br>ChatSessionManagerI::create(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;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;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Glacier2::SessionControlPrx</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">,&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;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;c)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;vname;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vname&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;validateName(name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_chatRoom</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">reserve(vname);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;reason)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;CannotCreateSessionException(reason);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Glacier2::SessionPrx&nbsp;proxy;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChatSessionIPtr&nbsp;session&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ChatSessionI(_chatRoom,&nbsp;vname);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;SessionPrx::uncheckedCast(c.adapter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">addWithUUID(session));&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::IdentitySeq&nbsp;ids;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ids.push_back(proxy</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">ice_getIdentity());&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sessionControl</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">identities()</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">add(ids);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::LocalException</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(proxy)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">destroy();&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;CannotCreateSessionException(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Internal&nbsp;server&nbsp;error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;proxy;&nbsp;<br>}</span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp; 首先调用一个简单的帮助函数 validateName, 来检查传递的用户名是否包含非法字符，并把它转为大写，然后调用 reserver函数把它加到聊天室的_reserved集合中。我们要监视这些操作抛出的消息，并把它转化为Glacide2::CannotCreateSessionException异常，即在create操作的异常规范声明的异常。<br>&nbsp;&nbsp;&nbsp;&nbsp; 接着实例化一个ChatSessionI对象（见下面）来创建会话。注意这个会话使用UUID作为对象标识，所以保证标识符唯一。<br>&nbsp;&nbsp;&nbsp; 最后，添加这个新创建的会话标识，Gllacier2只通过它来转发经过这个会话的请求。实际上，&#8220;只转发经过这个会话的并且只到这个会话的请求&#8221;，这是一种安全的办法：如果有恶意客户能猜出另一个客户会话的标识，它也不能向别的对象发送请求（可能在除了聊天服务器之外的服务器上）。如果出错，就销毁刚创建的会话对象，这样避免了资源泄露。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这就是利用Glacier2创建会话的全部。如果你希望使用Glacier2的认证机制，可以设置属性Glacier2.PermissionsVerifier为执行认证的对象代理。（Glacier2提供一个内置的权限验证器，NullPermissionsVerifier，可以检查用户名和密码）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图：会话创建交互图（略）<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ChatSessionI类实现了ChatSession接口。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ChatSessionI&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;ChatSession&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ChatSessionI(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomPtr</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setCallback(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackPrx</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Ice::Long&nbsp;send(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;destroy(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomPtr&nbsp;_chatRoom;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;_name;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ChatRoomCallbackAdapterPtr&nbsp;_callback;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;_destroy;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex&nbsp;_mutex;&nbsp;<br>};&nbsp;<br>typedef&nbsp;IceUtil::Handle</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ChatSessionI</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;ChatSessionIPtr;</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;构造函数设置聊天室和用户名，并把_destroy设置为False.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于Glacier2::create操作不允许传递代理，必须把创建会话和设置回调分成两步。这是setCallback的实现；<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;<br>ChatSessionI::setCallback(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;ChatRoomCallbackPrx</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;callback,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;c)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_destroy)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;Ice::ObjectNotExistException(__FILE__,&nbsp;__LINE__);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_callback&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">callback)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Ice::Context&nbsp;ctx;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ctx[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">_fwd</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">o</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_callback&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SessionCallbackAdapter(callback</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">ice_context(ctx),&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChatSessionPrx::uncheckedCast(&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.adapter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">createProxy(c.id)));&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_chatRoom</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">join(_name,&nbsp;_callback);&nbsp;<br>}</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意，在使用join传递代理之前，向客户代理添加了一个值为 "o" 的_fwd上下文。它提示Glacier使用单向调用来转发客户回调。这样比双向调用更加有效。因为所有的回调操作均为void返回值，所以可以单向调用。<br>&nbsp;&nbsp;&nbsp;&nbsp; 服务器的回调为普通的双向调用。这样当出错时可以通知服务器。当客户端出错时，这个对结束客户会话很有用。<br><br>&nbsp;&nbsp;&nbsp;&nbsp; 一旦客户调用了setCallback，就可以接收聊天室的各种行为通知。下为send实现：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Ice::Long&nbsp;<br>ChatSessionI::send(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;message,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_destroy)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;Ice::ObjectNotExistException(__FILE__,&nbsp;__LINE__);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">_callback)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;InvalidMessageException(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">You&nbsp;cannot&nbsp;send&nbsp;messages&nbsp;until&nbsp;you&nbsp;joined&nbsp;the&nbsp;chat.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;validateMessage(message);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;reason)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;InvalidMessageException(reason);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_chatRoom</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">send(_name,&nbsp;msg);&nbsp;<br>}</span></div>
<p>&nbsp;<br>&nbsp;&nbsp;&nbsp; 客户要离开聊天室，只要调用 destory.</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;<br>ChatSessionI::destroy(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::Current</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;c)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;IceUtil::Mutex::Lock&nbsp;sync(_mutex);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_destroy)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;Ice::ObjectNotExistException(__FILE__,&nbsp;__LINE__);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.adapter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">remove(c.id);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_callback&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_chatRoom</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">unreserve(_name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_chatRoom</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">leave(_name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Ice::ObjectAdapterDeactivatedException</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;No&nbsp;need&nbsp;to&nbsp;clean&nbsp;up,&nbsp;the&nbsp;server&nbsp;is&nbsp;shutting&nbsp;down.&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;_destroy&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;&nbsp;<br>}</span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/eXile/aggbug/77897.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2009-03-26 00:54 <a href="http://www.cppblog.com/eXile/archive/2009/03/26/77897.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[T] ICE实例学习：Let's Chat! 节译 (1)</title><link>http://www.cppblog.com/eXile/archive/2009/03/25/77890.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Wed, 25 Mar 2009 15:52:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2009/03/25/77890.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/77890.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2009/03/25/77890.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/77890.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/77890.html</trackback:ping><description><![CDATA[节译，原文地址：<a href="http://www.zeroc.com/articles/index.html"><u><font color=#0000ff>http://www.zeroc.com/articles/index.html</font></u></a><br><br><span style="FONT-SIZE: 18pt"><strong>需求<br></strong></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）一个典型的聊天室应用，使用客户器/服务器架构，客户发送消息到中心服务器，然后，消息发送给其它客户。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）尽量减少服务器管理，甚至可以不需要。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）通信必须安全，通过公共网络时必须要保护个人隐私。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4）当客户端和服务器有防火墙保护时也能正常运行，客户端不用修改它的网络或者防火墙设置。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5）客户端可以在各种平台上利用多种语言实现，比如说利用Web浏览器作为客户端。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6）客户端可能网络带宽有限，所以应该尽量减少网络流量。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 只支持单个聊天室。（多个聊天室只是代码多了点，并没有增加任何难度）。<br><br><span style="FONT-SIZE: 18pt"><strong>设计<br></strong></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在本文中，将会演示多种客户端的设计和实现。包括：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）C++命令行客户端；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）JAVA SWing GUI客户端；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）.NET WPF客户端；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4）PHP网页客户端；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5）Silverlight 网页客户端；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; 注意，对于ICE3.3, PHP和Ruby只提供了客户端的Run Time。我们在考虑当连接的客户如何从服务器获得消息时，必须要想到这一点。对于消息发布，有两种通信模型：<br>&nbsp;&nbsp;&nbsp;&nbsp; 1）推模型：略<br>&nbsp;&nbsp;&nbsp;&nbsp; 2）拉模型：略<br>&nbsp;&nbsp;&nbsp;&nbsp; 推模型比较简单，容易实现，我们的Chat 客户端中，C++，Java, .Net, Silverlight(0.3)都使用该模型。PHP客户端使用拉模型。<br><br><span style="FONT-SIZE: 18pt"></span><strong><font size=5>推模型定义<br></font></strong>&nbsp;&nbsp;&nbsp;&nbsp; 每个客户端中提供一个 ChatRoomCallback 类型的ICE对象到服务器。当发生事件时，服务器调用该对象的操作通知客户。SLICE定义如下：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Slice&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">module&nbsp;Chat&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Implemented&nbsp;by&nbsp;clients&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;ChatRoomCallback&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ami</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;init(Ice::StringSeq&nbsp;users);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ami</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;join(</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;timestamp,&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ami</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;leave(</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;timestamp,&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;name);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ami</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;send(</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;timestamp,&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;name,&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;message);&nbsp;<br>};&nbsp;<br>};<br></span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1）当用户首次连接到聊天室时，服务器调用 init 操作.&nbsp;&nbsp;&nbsp;&nbsp; users参数告诉用户目前连接到聊天室的所有用户信息。<br>&nbsp;&nbsp;&nbsp;&nbsp; 2）有用户连接到聊天室时，服务器调用 join 操作。<br>&nbsp;&nbsp;&nbsp;&nbsp; 3）有用户断开连接时，服务器调用&nbsp;leave 操作。<br>&nbsp;&nbsp;&nbsp;&nbsp; 4）有用户发送消息时，服务器调用 send 操作。<br>&nbsp;&nbsp;&nbsp;&nbsp; 注意设计使用异步事件。元数据指令 ["ami"] 标明服务器异步调用回调操作。当客户端行为异常时，这对服务器是一个保护：客户端可能长时间阻塞，服务器调用期间不会因此失去对线程的控制。<br><br><strong><font size=5>与防火墙协作<br></font></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 略......<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glacer2是ICE针对这种情况的预建的解决方案，它扮演一个服务器前端。Glacer2具有以下特征：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）支持会话概念，API支持认证机制，可实现自定义的会话创建和认证。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）单个Glacer2可进行任意数量的服务器和客户端转发。服务器只要有一个端口接受外来连接，而不用管具体服务器个数。<br>&nbsp;&nbsp;&nbsp;&nbsp; 3）对于具有防火墙的客户端，服务器也可调用其提供的回调。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为 Glacer2会话概念是面向连接的，只有当客户端同Glacer2的连接打开时，更精确的说，同Glacer2保持一个激活的会话时，服务器才可以对客户进行回调。换句话说，当客户端同Glacer2失去连接，Glacer2自动销毁会话。为了阻止客户端到Glacer2的连接被意外关闭，客户端必须要禁用ACM（Automic Connection Management, 自动连接管理）。而且，Glacer2通常对长时间空闲的会话设置超时。当聊天室长时间没有动作时，为了防止Glacer2销毁会话，客户端必须周期性进行激活，比如，调用 ice_ping, 来对Glacer2的会话超时进行重置。<br><br>&nbsp;&nbsp;&nbsp;&nbsp; Chat客户端通过服务器提供的 ChatSession接口来和服务器通信。 ChatSession 从Glacer2::Session派生。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Slice&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">module&nbsp;Chat&nbsp;<br>{&nbsp;<br>exception&nbsp;InvalidMessageException&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;reason;&nbsp;<br>};&nbsp;<br>&nbsp;<br></span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;ChatSession&nbsp;extends&nbsp;Glacier2::Session&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setCallback(ChatRoomCallback</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;cb);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ami</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;send(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;message)&nbsp;throws&nbsp;InvalidMessageException;&nbsp;<br>};&nbsp;<br>};<br></span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这就是推模型，Chat客户端调用ChatSession的send来发送消息，服务器调用每一个客户的ChatRoomCallback的send操作进行分发。<br><br><strong><font size=5>拉模型定义<br></font></strong><br>TODO<br><br><br>
<img src ="http://www.cppblog.com/eXile/aggbug/77890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2009-03-25 23:52 <a href="http://www.cppblog.com/eXile/archive/2009/03/25/77890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用ICE实现一个简单的聊天室</title><link>http://www.cppblog.com/eXile/archive/2009/01/04/ice.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Sat, 03 Jan 2009 17:32:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2009/01/04/ice.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/71099.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2009/01/04/ice.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/71099.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/71099.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 聊天室是一种典型的网络应用，这个程序演示了ICE框架的基本结构。&nbsp;&nbsp;<a href='http://www.cppblog.com/eXile/archive/2009/01/04/ice.html'>阅读全文</a><img src ="http://www.cppblog.com/eXile/aggbug/71099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2009-01-04 01:32 <a href="http://www.cppblog.com/eXile/archive/2009/01/04/ice.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用boost::asio实现一个简单的服务器框架</title><link>http://www.cppblog.com/eXile/archive/2008/05/28/51430.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Wed, 28 May 2008 13:00:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2008/05/28/51430.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/51430.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2008/05/28/51430.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/51430.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/51430.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 利用boost::asio实现一个简单的服务器框架&nbsp;&nbsp;<a href='http://www.cppblog.com/eXile/archive/2008/05/28/51430.html'>阅读全文</a><img src ="http://www.cppblog.com/eXile/aggbug/51430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2008-05-28 21:00 <a href="http://www.cppblog.com/eXile/archive/2008/05/28/51430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Reactor模式中网络事件分派探讨</title><link>http://www.cppblog.com/eXile/archive/2008/05/22/50767.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Thu, 22 May 2008 07:27:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2008/05/22/50767.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/50767.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2008/05/22/50767.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/50767.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/50767.html</trackback:ping><description><![CDATA[<br>原文地址:　<a href="http://www.cppblog.com/eXile">http://www.cppblog.com/eXile</a><br><br>&nbsp;　　对于使用线程池的Reactor模式，针对每一个SOCKET句柄的事件处理器handler可能被分派到不同的线程当中，这就要求handler的每一个操作都是线程安全的。<br>　　可以使用一种办法使一个handler的操作只能分派到一个线程中：为每一个handler设定一个线程所有者ＩＤ，一开始ＩＤ为空，则每个线程都可以分派，第一次分派之后，则设定为该线程ＩＤ，以后只分派到该线程中。这样，可以保证handler操作的单线程性，简化以后handler的具体实现。这个ＩＤ也可以灵活设置，以适应具体事务的要求。<br>　　但这样并不能保证handler彻底无锁，因为还会有两个线程会出现竟争，除了这个事件处理线程以外，还有事件分派线程（即事件侦听线程）。对于这个问题的解决办法如下：为每个handler设定一个原子计数，事件分派线程在分派事件前，首先设定该原子计数，若设置失败，表明此时正有其它线程在处理该handler，则并不分派该事件，而是将它置于一个pending队列中，等待以后分派。<br>&nbsp;　　还有一种简单的方法，就是将该handler直接挂起，处理完后才允许进行事件分派。 
<img src ="http://www.cppblog.com/eXile/aggbug/50767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2008-05-22 15:27 <a href="http://www.cppblog.com/eXile/archive/2008/05/22/50767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost::asio示例HTTP Server类图</title><link>http://www.cppblog.com/eXile/archive/2008/05/07/49072.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Tue, 06 May 2008 16:50:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2008/05/07/49072.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/49072.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2008/05/07/49072.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/49072.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/49072.html</trackback:ping><description><![CDATA[<p><a href="http://www.cppblog.com/images/cppblog_com/exile/asio_http_1.jpg"><img height=652 alt="" src="http://www.cppblog.com/images/cppblog_com/exile/asio_http_1.jpg" width=878 align=left border=0></a><a href="http://www.cppblog.com/images/cppblog_com/exile/asio_http_1.jpg"></a></p>
<img src ="http://www.cppblog.com/eXile/aggbug/49072.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2008-05-07 00:50 <a href="http://www.cppblog.com/eXile/archive/2008/05/07/49072.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高性能服务器的多线程策略</title><link>http://www.cppblog.com/eXile/archive/2008/03/06/multithread.html</link><dc:creator>eXile</dc:creator><author>eXile</author><pubDate>Wed, 05 Mar 2008 16:09:00 GMT</pubDate><guid>http://www.cppblog.com/eXile/archive/2008/03/06/multithread.html</guid><wfw:comment>http://www.cppblog.com/eXile/comments/43780.html</wfw:comment><comments>http://www.cppblog.com/eXile/archive/2008/03/06/multithread.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/eXile/comments/commentRss/43780.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/eXile/services/trackbacks/43780.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: （一）线程数量与线程池模型 （二）多线程的内存池优化&nbsp;&nbsp;<a href='http://www.cppblog.com/eXile/archive/2008/03/06/multithread.html'>阅读全文</a><img src ="http://www.cppblog.com/eXile/aggbug/43780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> 2008-03-06 00:09 <a href="http://www.cppblog.com/eXile/archive/2008/03/06/multithread.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>