聊天室技术内幕ABC.

来源:互联网 发布:摄影教程视频 知乎 编辑:程序博客网 时间:2024/05/22 12:49

  写聊天室的话,有很多技术可以使用,但是除了技术以外,该实现哪些功能也是要事先考虑好的,具体哪些功能更贴近用户、更实用,可以去问一些经常聊天的网友,他们一般会给你一个较满意的答复。至于技术方面,如Perl、CGI(exe)、ASP、ISA都是可以使用的基础的服务器端技术,ActiveX、Java、VBScript和JScript则是客户端技术。

  从效率来讲,所列出的服务器端技术的效率依次提升的;客户端技术则是依次下降,但VBScript和JScript效率相近。

  从功能来讲,ISA的功能最强,CGI(exe)其次,Perl没用过;客户端是ActiveX最强,JScript、Java其次、VBScript没用过 :P。

  从易用性来说,ASP最强,Perl其次,ISAPI最次;客户端是VBScript和JScript最好,Java其次。

  根据我的理解,聊天室大体可分为两类:基于刷新的和基于Server Push的。以前(包括现在很多)的聊天室是基于刷新的,这样的好处是——实现容易。缺点是:首先,服务器端必须保存足够的用户发言,严重影响服务器端性能,还有,由于经常传送重复的信息,对网络的带宽是极大的浪费;其次,用户发出的信息不能立刻展现给其它用户,当然,提高刷新间隔可以改善这种状况,但是,这将造成更大的网络负载。Server Push技术是最近新兴的技术,它只需要用户进行一次(或很少的几次)请求,然后不断的给用户发送最新到达的信息,有效的避免了上述弊端;它的缺点是实现难度较大。这里主要讨论一下Server Push技术的聊天室。

  早些时候见到,NS浏览器支持一种Push形式的MIME编码(x-???),其中后面的数据段可以自动覆盖前面的数据段,据说用它可以较容易的实现Server Push,但由于其仅被NS支持,而IE不支持,所以没有深究,有兴趣的话可以查阅相关资料。

  有一种方法可以同时在IE中和NS中实现Server Push,那就是利用“未完成(PENDING)的页面”。众所周知,在浏览某些较大得网页,而带宽又较小时,网页会一部分一部分的陆续展现给用户,利用这一点,就可以实现高性能的聊天室。服务器端要做的就是,在有要发送给用户的信息时,将信息照常发送,但是,当暂时没有新的信息时,不是去关闭连接,而是就此挂起,不向用户发送任何信息,直到新的信息到达。当新信息到达时,发送立即恢复,就像从来没有中断过一样。这样,从客户端来看,与浏览速度较慢的网页没有什么区别。从聊天室的角度来看,用户只需要提交一次请求,直到退出都有效,避免了重复刷新;在网络上只传输有必要传输新信息,有效的利用了网络的带宽;所有新信息立即发送,而不必等待用户刷新,增强了即时性。

  举一个例子:263(首都在线)的聊天室就使用了这种技术,我们来分析一下:

  其客户端使用了框架,有一些控制性、协调性的脚本驻留在主框架中。PENDING页面就是显示所有用户发言的页面(一个框架)。当一个新的信息被Push到这个框架中时,它带有一个立即执行的脚本,这个脚本以信息内容作为参数,调用驻留在主框架中的函数。主框架中的函数将信息内容写回到发言页面中,同时也负责更新右边的用户列表。PENDING页面是提交到服务器的一个特殊端口的(非80口),该端口上有一个服务在监听(LISTENING),它的任务就是——在HTTP协议上实现PENDING,具体这个服务是怎么回事我就不得而知了,实现起来不会很难。

  但是,263这种做法我不认为是最好的。首先说它的服务器端实现:使用一个专门的端口并不是明智之举,将这个服务整合到www服务内应更方便一些(毕竟你要以www方式才能与用户交互,整合入www服务,可获得www服务提供的许多支持)。客户端做的工作太少了,现在的客户端都有较强的性能,不利用,难道是怕用户发怒么?节省下的服务器端资源可以更好(例如更及时)的为用户服务。当用户数目大量增加时,服务器端资源是有限的,会很快的背消耗,但是,客户端资源却是同比例增长的。因此,只要可能,将工作放到客户端去做。多数情况下,这样做还可以节约网络带宽。

  那么,来说一下我的实现(先声明一下,我没有剽窃263的任何内容,当我的第二个聊天室主体完工时,才发现263使用了类似的技术——我几乎不聊天,呵呵)。我有两个聊天室实现(当然,第二个更好一些),但都使用了类似的技术。第一个聊天室是完全基于ISAPI 的,当时只是想证明Server Push技术可以实现,效率较低下,维护起来也很麻烦;第二个,就是现在即将推出的,将ISAPI、ASP和COM组合使用,得到了更好的维护性(受益于ASP),核心部分针对Win2000进行优化,获得了较高的性能。(平心而论,第一个实现所“可能”获得的最大效能要远大于第二个,但是,第一个的可维护性相对第二个实在是天壤之别,折中后,还是第二个好 J )我直接说第二个实现了~~~(爱慕虚荣的家伙)。

  ISAPI部分负责网页的PENDING;COM部分负责计算密集或时间敏感的操作和管理,同时负责ISAPI部分与ASP部分的交互;ASP部分不用说,负责绝大部分(除PENDING页面外的)与客户端的交互,以及一些轻量级的管理事务。在客户端,不使用框架组(FRAMESET),而使用单一页面内嵌IFRAME。使用两个IFRAME作PENDING页面,轮流提交。即,当一个盛放了过多的信息时,自动提交下一个,清除原来的,避免客户端缓存过多的废信息。使用一个短间隔的定时器,不断检查是否有新消息被Push进来,如果有,将消息卸包,分发到相应IFRAME,驻留在相应IFRAME中的脚本负责将消息以某种形式表现出来。

  (说明:IE没有提供感知新消息到达PENDING页面的途径,我曾妄想通过ondateavailable来得知,结果失败了,只好使用定时器,这么做的弊端是,从消息到达到表现出来可能会有一个延迟,这个延迟的最长时间是定时器触发间隔。也许我应该向263那样连脚本一起Push,但万一传送错误,可能导致IE报错,而采用检测机制可以用try块捕获错误,能够自恢复;如果每个Push消息脚本都用try块包裹,即使错误被捕获,也不容易处理——处理程序也在PENDING页面中,如果它也传错了怎么办?既然前面的脚本都错了,try本身会不会也错了?…………我还需要考虑考虑)。

  上面所说的只是主体结构,具体到实现细节就很多了,差不多要贴源代码了。上面的内容都是较容易从实现的表现中分析出来的,我就不难为大家去费力分析了,反正也有可能能被分析出来(注意:不是一定能),不如公布出来。而服务器端的实现细节,目前我不打算公布(不会也能分析出来吧?也许会公布,看我们内部如何决定了),因为可能涉及将来的安全性;但主体结构有了,思路就有了,我认为这是最重要的部分,只要稍有能力,就可以设计一个服务器端出来,可能比我的要好很多。至于客户端实现,当然,稍微使用点手段就可以掌握每个细节,为方便大家,节省大家时间,当我们的聊天室客户端基本定型后,我会把它打成包,供大家自由下载J。