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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.15/5 (13投票s)

2004年1月22日

5分钟阅读

viewsIcon

93287

downloadIcon

2411

这是一个关于编写基于 Web 的聊天的分步文章。本文解释了最简单的聊天。

Sample Image - SimpleChat.gif

引言

在 Web 上最受欢迎的活动之一是参与 Web 聊天 - 协作应用程序,它们提供了一种机制,可以在实时中让两个或多个用户进行对话。为任何网站添加的有用功能是能够按兴趣将用户分组到单独的聊天室中。有些网站允许在不注册的情况下参与聊天,但大多数网站不行,因为注册可以提供更安全的聊天和更精确的控制。即使是更安全的聊天环境,也是由管理员或版主监控聊天过程,删除威胁性痕迹,并防止其将来再次发生。但是,系统还必须自动阻止用户的不当行为。有聊天规则、脏话过滤等。聊天系统还必须在不同平台上的各种浏览器上运行。在这里,我们将使用 ASP、JavaScript 和一种用于共享服务器端数据的工具来描述聊天开发。在我们的例子中,就是 XML。

背景

为了简化学习任务并专注于细节,我们的聊天开发分为四个阶段。

  • 简单聊天:提供基本功能:单个聊天室、消息历史记录、发送消息的可能性、恶意输入过滤、发送者 IP 地址跟踪和调用聊天帮助。
  • 用户友好型聊天:除了之前的基本功能外,还提供活动用户列表。启动页面上的用户数量也是必需的。它有注销功能,并在指定超时后自动让不活跃用户过期。
  • 可注册聊天:在此,添加了用户信息和注册的持久性。用户管理和关系数据库支持可能很有用,但在此省略。
  • 宫殿聊天:该功能是多个聊天室。在此,用户登录后,将为每个房间显示活动用户数量。有用的可能性是无需退出即可更改房间,以及无需第二次登录即可打开独立房间。获得了提供额外工具栏命令的要求:打开房间和更改房间。

本文介绍了一个简单的聊天。

简单聊天

让我们从基本的设计布局开始。有三个窗格:工具栏、消息历史记录和新消息表单。它们是独立的,没有直接的连接。

仅使用 HTML 不可能实现回调机制,例如客户端监听服务器事件。因此,要查看更改,现有的唯一方法是定期刷新页面。在这种情况下,仅消息历史记录需要自动刷新页面。工具栏命令和发送新消息由用户操作执行,因此不需要自动刷新。正确的系统工作需要一个唯一的存储消息的位置。这在图 1 中得到了说明。

图 1 - 简单聊天图。

执行自动页面刷新的最简单方法是使用 HTML 标题中的 META 标签

<META HTTP-EQUV="Refresh" Content="7">

此定义会导致页面每 7 秒刷新一次。为了方便维护,您可以更进一步,将其设置为常量。示例定义在 Settings.js

function getMessagesRefreshTime() {
    return 7;
}

因此,我们的消息历史记录页面的标题将如下所示

<META HTTP-EQUV="Refresh" Content="<%=getMessagesRefreshTime();%>">

所有消息都收集在服务器上。在每次消息历史记录的 HTTP 请求时,都会对所有消息进行 HTML 格式化。浏览器会下载它。为防止下载过多消息,应删除最旧的消息。这可以通过使用溢出启用的机制来实现,如图 2 所示。

图 2 - 溢出启用的机制。

在数组中添加新项后,将删除最后一项。这仅在已填满最大项数时发生。因此,数组中的项数不超过允许的最大值。这个技巧是在 LimitedXML 类中实现的。

...

/**
 *  Adds new item.
 *  @param value value to add.
 */
function LimitedXML_add(value) {
    var xmlDoc = this.getXMLDocument();
    var element = xmlDoc.createElement(this.xmlSection);
    var elementText = xmlDoc.createTextNode(value);
    var root = xmlDoc.firstChild;
    root.appendChild(element);
    element.appendChild(elementText);
    this.removeSuperfluous(root);
}

/**
 *  Removes superfluous items.
 *  @param root XML node for the root.
 */
function LimitedXML_removeSuperfluous(root) {
    var items = this.getItems();
    if(this.nMax < items.length) {
        root.removeChild(items.item(0));
    }
}

...

消息存储必须符合以下要求

  • 对所有客户端请求共享
  • 线程安全
  • 必须提供添加新项、删除和快速迭代的可能性

XML 和 MS XML 解析器的 FreeThreadedDOMDocument 符合这些要求。通过 Application 对象实现了对所有客户端请求的消息数据的共享。共享 XML 存储和项检索的通用功能也在 LimitedXML 类中实现。它提供了以下公共方法:add(value)getItems()。此类还包括使用前面描述的方法删除过时的项。

为了专门针对聊天消息,提供了 Messages 类,并在 MessageClass.js 中定义。在这里我们执行

  • 初始消息格式化,包括发送者姓名、IP 地址、消息本身和表情图标
  • 添加新消息
  • 添加系统消息
  • 将消息历史记录格式化为 HTML

消息处理的说明在此图表中显示

图 3 - 消息处理图

此外,强烈建议过滤用户输入中的恶意行为。这些是消息或用户名中的非文学性词语、特殊符号组合、客户端脚本或结束标签(例如 </html>)。所有过滤都应在添加消息之前执行。最合适的是 Messages 类及其 AddMessage() 方法。非文学性词语的处理委托给 Filter 类,在 IncorrectInputFilter.js 中表示。其他可能性是通过调用 Server.HtmlEncode() 方法来限制的。它将 HTML 特殊符号替换为表示模拟(> < & 等)。如果用户输入了多行文本,它也必须在消息历史记录中显示为多行。这是通过将换行符替换为 <BR> 标签来实现的。

单词过滤算法基于用点替换所有不可打印单词的出现。该算法使用正则表达式实现。搜索模式可能如下所示

/badword1|badword2|...|badwordN/ig

此模式提供了搜索列出的任何“脏话”的可能性。模式的结尾指定了正则表达式选项:i 导致忽略大小写,g 允许全局搜索或在整个文档中搜索。

这里,badword1badword2、...、badwordN 必须替换为实际的不可打印单词。示例可在 IncorrectInputFilter_getPattern() 方法中找到。使用 JavaScript 进行替换由以下几行组成

function IncorrectInputFilter_processText(inputText) {
    var s = new String(inputText);
    return s.replace(this.getPattern(), "...");
}

检查简单聊天示例的源代码。

这种类型的聊天有一些缺点

  • 可能重复用户名
  • 整个 frameset 的刷新会导致系统添加新的用户加入消息
  • 如果浏览器禁用了 JavaScript,聊天中的大多数链接将无法重定向。

关注点

我不是网页程序员,但我喜欢学习有趣的东西。基于 Web 的聊天就是其中之一。目前,我正在从事个人开发计划和提高工作时间效率。

© . All rights reserved.