65.9K
CodeProject 正在变化。 阅读更多。
Home

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

2004年1月22日

5分钟阅读

viewsIcon

99677

downloadIcon

1819

ASP 聊天系列最后一篇。本文讲解如何为聊天提供多房间功能。

Sample Image - PalaceChat.gif

引言

本文介绍为现有聊天应用程序提供多房间功能的步骤。

宫殿聊天

这种类型的聊天是最难实现的。需要对每一个细节都给予额外的关注。我们需要决定如何按房间划分用户和消息。第一个方法来自关系理论——为每条消息和每个会话添加一个新字段,该字段唯一标识一个房间。或者简单地提供“房间”表与“消息”表,“房间”表与“会话”表之间的一对多关系。

图 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.aspnewroom.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。
© . All rights reserved.