使用 JavaScript 和 XML 编写 ASP 聊天(第 4 部分)





4.00/5 (4投票s)
2004年1月22日
5分钟阅读

99677

1819
ASP 聊天系列最后一篇。本文讲解如何为聊天提供多房间功能。
引言
本文介绍为现有聊天应用程序提供多房间功能的步骤。
宫殿聊天
这种类型的聊天是最难实现的。需要对每一个细节都给予额外的关注。我们需要决定如何按房间划分用户和消息。第一个方法来自关系理论——为每条消息和每个会话添加一个新字段,该字段唯一标识一个房间。或者简单地提供“房间”表与“消息”表,“房间”表与“会话”表之间的一对多关系。
图 5 - 使用关系理论按房间划分数据
虽然这种方法适用于 XML 和关系数据存储,但它最适合关系数据库,而不适合 XML。
第二个方法利用了 XML 的层次结构。在这里,不需要额外的带外键的属性。包含一个 ROOM
节点将提供快速的房间数据标识和访问。
<ROOT>
<ROOM id=1 name="room 1 name">
<ITEM>Message body 1</ITEM>
<ITEM>Message body 2</ITEM>
</ROOM>
<ROOM id=2 name="room 2 name">
<ITEM>Message body 3</ITEM>
<ITEM>Message body 4</ITEM>
. . . . .
</ROOM>
</ROOT>
会话也通过相同的方法按房间划分。出于性能原因,它们被放置在不同的 XML 文档中。理论上,这种情况更快——房间的搜索只在一级层次结构(ROOM)中进行。这与关系数据查询相反,后者中的每个记录标识一个房间子集。
将此方法应用于现有聊天逻辑需要提供一个新类。这个类必须像 SharedXML
类一样运行,但它处理构造函数中指定的 XML 节点。它的构造函数原型是 SingleLevelXML(xmlNode)
。SharedXML
类的大多数方法都可以用在 SingleLevelXML
类中,只需做最小的更改。为了重用行为,我们需要在类构造函数中指向 SharedXML
类中已定义的那些方法。
// SingleLevelXML class.
function SingleLevelXML(xmlNode) {
this.xmlNode = xmlNode;
this.getWorkingNode = SingleLevelXML_getWorkingNode;
this.xmlSection = "ITEM";
// Reuse of SharedXML functions.
this.addNode = SharedXML_addNode;
this.insertNode = SharedXML_insertNode;
this.insertXmlNode = SharedXML_insertXmlNode;
this.findNode = SharedXML_findNode;
this.findNodeByName = SharedXML_findNodeByName;
this.removeNode = SharedXML_removeNode;
this.setAttribte = SharedXML_setAttribte;
this.getItems = SharedXML_getItems;
}
对于两个类,getXMLDocument()
方法必须被替换为 getWorkingNode()
。进行此替换是为了更好地代码重用。LimitedXML
类也需要同样的更改。
添加多房间功能至少需要两个新页面。它们是 roomslist.asp 和 newroom.asp。第一个页面提供要加入的房间选择以及每个房间的活跃用户数。第二个页面允许我们定义一个新房间。
roomslist.asp 在成功登录后由起始页引用。这个角色导致将授权和会话创建例程移至 roomslist.asp 页面。但是用户登录后进入哪个房间?为了解决这个问题,我们将提供一个临时房间或隐藏房间。这个房间仅供内部使用,用户登录成功后会被添加到其中。选择一个有效房间后,会话记录会被移至相应的房间节点。这个技巧为以下两个功能开了绿灯:无需重新登录即可切换房间和打开单独的房间。
房间切换的执行方式与进入聊天的方式相同:移动会话记录。打开一个单独的房间会导致克隆一个会话,使其位于另一个房间节点中。具体来说,它看起来像“三个杯子算法”。
图 5 - “三个杯子算法”
前两个杯子是真实房间。第三个杯子是隐藏房间。在当前设计中,用户在不退出或打开单独窗口的情况下无法选择另一个房间。一个隐藏房间可以帮助解决这个问题。将用户记录移动或复制到隐藏房间并显示可用房间列表非常简单。用户选择一个房间后,聊天应用程序的行为就和登录后进入房间时一样:用户记录从隐藏房间移动到目标房间。
/**
* Move user from one room to another.
*/
function UserManager_switchRoom(roomIDOld, roomIDNew, sessionID) {
var previousRoom = this.getRoomSessions(roomIDOld);
var oldXmlNode = previousRoom.findNode(sessionID);
if(oldXmlNode != null) {
var targetRoom = this.getRoomSessions(roomIDNew);
var xmlNode = targetRoom.findNode(sessionID);
if(xmlNode == null) {
// Session not exist in the target room. Move a session.
xmlNode = oldXmlNode.cloneNode(false);
targetRoom.insertXmlNode(xmlNode);
var newSession = new Session(xmlNode, true);
newSession.markLastAccessTime();
}
// Removing from previous room.
previousRoom.removeNode(oldXmlNode);
}
}
应用程序设置
本文包含四个迭代,它们都是可运行的示例。它们是:
- 简单聊天(Samples\SimpleChat)。
- 用户友好聊天(Samples\UserFriendlyChat)。
- 可注册聊天(Samples\RegistrableChat)。
- 宫殿聊天(Samples\PalaceChat)。
所有这四种应用程序都有相似的 IIS 安装过程。在 IIS 管理面板中,为每种所需的聊天类型定义虚拟目录。将它们指向样本的相应磁盘位置,并添加 \XMLChat 子文件夹。对于简单聊天,如下所示:
- 虚拟目录名称:SimpleChat
- 内容目录:[您的本地路径]\Samples\SimpleChat\XMLChat\
访问权限可以为默认值:读取和脚本执行。为获得更好的性能,应禁用会话状态。
可注册聊天和宫殿聊天还需要具有读写权限的文件夹。它们还需要一个 DB 文件夹,该文件夹不是 Web 应用程序的子文件夹。例如:[您的本地路径]\Samples\SimpleChat\DB\。
完成这些步骤后,您就可以浏览和尝试聊天了。如果不起作用,您可能需要在服务器端安装 MS XML Parser 3.0 或更高版本。它随 IE 5.0 及更高版本一起提供。
聊天设置可以在 INC/Settings.js 文件中进行自定义。以下是可自定义函数的列表:
getMessageRefreshTime()
- 指定消息历史窗格下次刷新间隔的时间(以秒为单位)。getVisitorsRefreshTime()
- 与上一个相同,但用于活跃用户窗格。getSessionExpirationTime()
- 指定断开连接的用户过期的超时间隔(以秒为单位)。getMaxMessages()
- 指定要为用户显示的最大消息数量。getUsersDataPath()
- 指定用于存储持久用户信息的磁盘位置。getRoomsDataPath()
- 与上一个相同,但用于存储房间信息。
建议的增强功能
在本文中,我们描述了四个功能日益复杂的聊天应用程序,但与任何其他程序一样,它们还可以进一步升级。首先,可以增强用户和房间的管理功能。另一种有用的可能性是个人聊天室,仅供两人使用。为了提供良好的设计适应性,可以将级联样式表(CSS)应用于每个页面。
可注册聊天和宫殿聊天对注册用户数量有限制。由于整个用户注册存储都由 XML 解析器加载到内存中,因此它不能大于可用物理内存大小除以十。为避免此问题,我们可以增加物理内存或提供关系数据库来存储用户。
结论
在这里,我们提供了一套不错的聊天应用程序:从简单到高级。每个聊天应用程序都是前一个版本的改进。
对于每种聊天类型,我们都解释了最困难的细节和一些技巧。所有四个聊天示例都使用了面向对象的方法(JavaScript 允许这样做)。特别关注了性能方面。所有示例都是完整的,并且已准备好集成到实际站点中。所有示例都在不同平台上的各种浏览器中进行了测试。
- Windows:Internet Explorer 版本(4、5、6)、Netscape 版本(4.7、6、7)、Opera 6。
- Linux:Netscape 4.6。
- Mac:Netscape 4.7、Internet Explorer 5.0。