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






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

80284

2340
关于编写基于 Web 的聊天的分步文章。本文介绍了带用户列表的聊天。
引言
聊天的下一个级别是用户友好的聊天。除了先前的功能外,这还提供了活动用户列表。启动页面上的用户数量也是必需的。它具有注销可能性,并在指定超时后使不活跃用户过期。
用户友好的聊天
将简单聊天升级为用户友好聊天需要一个共享位置来存储活动用户。方便的方法是使用 XML DOM。主要原理与前一个示例中的消息存储相似。为了泛化任务,活动用户一词被替换为用户会话。对于此类聊天,用户会话基本上应包含唯一的会话标识符和用户名。
我们的存储功能由两个类实现:SharedXML
和 Session
。第一个类为标准访问函数提供访问共享数据的可能性。这些是项插入、删除、按标识符或名称快速搜索项以及为新字段生成唯一 ID。它封装了 XML DOM 处理。第二个类提供了对带有会话信息的 XML 节点的便捷访问方法。
让我们回到聊天用户界面。在进入聊天之前,许多用户会想知道当前有多少人可以聊天。要访问此信息,服务器端逻辑应包含 ChatProcessing.asp 中的 getActiveUsersCount()
函数。
只有在没有活动用户具有相同姓名的情况下,登录操作才能成功完成。但也有可能用户断开网络连接或意外关闭了聊天。在这些情况下,需要一种机制来重复用户授权。它可以是第一次和第二次登录比较,从同一台计算机请求。在此示例中,它是使用客户端 IP 地址跟踪实现的。在服务器端,它使用 loginUser(userName)
函数处理。
登录后,用户将想知道谁可以聊天。为此,我们提供第三个面板 - 活动用户列表。这是一个每隔几秒刷新一次的框架。此框架刷新的实现与消息框架中的相同。
<META HTTP-EQUV="Refresh" Content="<%=getUsersRefreshTime();%>">
在此页面上,使用服务器端函数 formatUsers(sessionID)
从 ChatProcessing.asp 中执行指定会话的活动用户列表表示格式化。
当用户完成聊天后,他们将希望退出聊天,因此需要注销工具栏按钮和 logoutUser(sessionID)
函数。按下此按钮将立即删除用户。但是,用户应该可以通过退出而不通过按钮注销来退出,例如,如果他们关闭了浏览器窗口或浏览到另一个网页。处理这些情况需要一个会话过期机制。一种可能的实现方法是跟踪用户上次访问会话的时间。此时间是会话信息的一部分。定期检查过期的会话将删除未使用的会话。下面是 FormatUsers
函数的说明。
要实现的功能总结
loginUser(userName)
- 将用户添加到活动用户列表;logoutUser(sessionID)
- 将用户从活动用户列表中删除;getActiveUsersCount()
- 检索当前登录用户的数量;formatUsers(sessionID)
- 为指定会话格式化用户列表。
会话信息包括
- 唯一的会话 ID,
- 用户名,
- 客户端 IP 地址,
- 上次访问时间。
为了维护 UserManager
类提供的良好架构设计,该类封装了用户和会话管理功能,并与 SharedXML
和 Session
类协同工作。设计如图 4 所示。
图 4 - 用户友好聊天类图。
所有实现都很清晰。loginUser()
检查是否存在同名用户。如果未找到,则创建一个具有唯一 ID 的新会话。它还将用户名和客户端 IP 地址与新创建的会话关联起来。logoutUser()
按 ID 搜索现有会话并将其删除。getActiveUsersCount()
通过计算共享会话集合的长度来检索活动用户数量。formatUsers()
方法实现双重功能:格式化用户以在活动用户面板中显示,并检查会话过期。第二个功能放在这里,因为它不需要额外的记录迭代。因此,活动用户格式化和检查过期会话在单个循环中执行。下面是该方法的列表。
function UserManager_formatUsers(sessionID) {
if(!this.isValidSession(sessionID)) {
return "";
}
var users = new SharedXML(this.identifier);
var strUsers = "";
var items = users.getItems();
var i = 0;
while(i < items.length) {
var x = items.item(i);
if(!this.checkExpiration(x)) {
var s = new Session(x, false);
var id = s.getSessionID();
if(sessionID == id) {
var continueSession = new Session(x, true);
continueSession.markLastAccessTime();
}
strUsers += s.getUserNick();
strUsers += "<BR>\n";
}
i++;
}
return strUsers;
}
此方法的另一个重要细节是防止其他用户标记他人会话的最后访问时间。为此,此处创建的 Session
对象带有 false
的第二个构造函数参数。
var session = new Session(xmlNode, false);
此值表示在使用此对象时,不标记会话的最后访问时间。
function Session_markLastAccessTime() {
if(this.markAccesssing) {
var currentTime = new Date();
var lastAccessTime = currentTime.valueOf();
this.setAttribte("ACCESSED", lastAccessTime);
}
}
结论
此聊天的一个不便之处在于,不同时间可能有多个用户共享同一个名字。在下一部分中,将通过实现注册机制来解决此问题。