内容


使用 Ajax 实现聊天功能

简介

使用过即时消息聊天软件的人,可能都会想要找到一种免费的、开源 Web 聊天软件,在这样的软件中,您可以使用自己的代码定制聊天的外观和感受以及它向服务器上的数据库发送消息的方式。有了 Ajax Chat,您就可以停止寻找了,Ajax Chat 是一种用 JavaScript、PHP 和 MySQL 实现的应用程序,在 GNU Affero General Public License 下发布。

Ajax Chat 有两种版本 — 独立版和论坛集成版。您可以随心所欲地添加或减少频道。只要不影响现有资源,在所托管的环境内就没有最大聊天频道数的限制,并且添加频道(以及用户和数据库)也不会有任何成本。

借助 Ajax Chat,可以发送私人或广播消息、删除聊天内的消息、定义聊天的开放时间、设置长度计数器,以及使用 Cascading Style Sheets (CSS) 和模板系统定制布局。Ajax Chat 还具有安全性,能够防止代码注入、SQL 注入、跨站点脚本攻击、会话偷窃以及其他攻击。只需确保系统能够提供聊天漏洞的应对之策以防止黑客利用这些漏洞进行攻击。

频道期望清单(wishlist)

可以将其中的一个频道作为系统和用户管理员用来发送和接收系统状态实时告警的专用频道。例如,可以使此频道由系统事件触发后弹出,然后发出警告声音并在认定您当前刚刚离开客户机后发出呼叫以引起您的立即注意。以下是系统事件的一些例子:

  • 系统性能下降到服务水平协议(Service Level Agreement,SLA)内定义的服务保证水平之下时
  • 将性能恢复到该服务水平的建议工具
  • 性能恢复的进展状态
  • 性能回到服务保证水平时
  • 性能低于服务水平的时长以及它在系统内发生的位置

期望清单包含了管理员聊天功能的第二个面板以便向用户广播消息,例如,性能等级的状态或 socket 服务器何时需要因维护和修理而关闭,以及它们何时能重新启动。当系统正常运行时,开发人员和管理员可以使用这个第二个面板来指向行业范围的开源 Ajax 库。

为了侦听聊天消息,必须确保聊天客户机能够建立与此 socket 服务器的永久连接。因为,在默认情况下,只有本地客户机(127.0.0.1,::1)可以广播消息,若要允许其他客户机(比如,您的系统管理同事)发送广播消息,就需要更改默认设置。

下载 Ajax Chat

首先进入 SourceForge.net 的 Blueimp Ajax Chat。这里有几个文件压缩包。应该下载并解压缩的第一个文件当然是主要的聊天应用程序文件:ajax_chat-0.8.1.2.tar.gz。

这些文件解压缩后会被自动放入如下的文件夹:css、 flash、img、js、lib、socket、sounds 和 src。其他还需下载的文件将集成 Ajax Chat 与 phpBB2、phpBB3、MyBB、PunBB、SMF、vBulletin 和其他的 PHP 社区文件。

在上传并安装服务器端聊天文件之前,需要编辑三个配置设置:database、channel 和 user。在上传了这些文件之后,创建数据库表,然后删除安装脚本。此外,在服务器上还必须安装 MySQL。

数据库设置

在服务器上,可以将 Ajax Chat 设置为独立版,也可以使用论坛集成版。但是,需要更改默认配置来增强安全性。

使用独立版

要使用 Ajax Chat,首先进入 lib/config.php 文件。如果想要在服务器上使用 Ajax Chat 的独立版,就需要将主机、用户名、密码和数据库名设置为您的本地主机、用户名、密码和数据库名,如清单 1 所示。

清单 1. 针对独立版的数据库配置
$config['dbConnection']['host'] = 'localhost';
$config['dbConnection']['user'] = 'your_database_username';
$config['dbConnection']['pass'] = 'your_database_password':
$config['dbConnection']['name'] = 'your_database_name';

默认情况下,数据库配置 typelink 被设为 null。如果 type 被设为 null,它就会默认为 mysqli,也可以将其更改为 mysql。而 link 则可被设为对现有数据库连接或对象的一个引用。如果将 link 设为 null,就会创建一个新的数据库连接。

使用论坛集成版

如果更愿意使用论坛集成版,可以通过将所有数据库配置都设为 null 来让 Ajax Chat 使用论坛的现有数据库连接。若为论坛集成版使用的是另外一个不同的数据库,就必须注释掉 lib/class/CustAJAXChat.php 文件内的一行。比如,对于 phpBB3 集成版,必须注释掉如下的一行:

$this->setConfig('dbConnection', 'link', $db->db_connect_id);

完成后,可以如同对独立版所做的那样对数据库进行设置。

如果想要将此聊天功能用作论坛内的在线留言板(shoutbox),需要更改聊天目录的 URL 和路径。为此,先要进入 includes/functions.php 文件查找此聊天文件夹的 URL 和路径,比如:

define('AJAX_CHAT_URL', '/chat/');
define('AJAX_CHAT_PATH', realpath(dirname($_SERVER['SCRIPT_FILENAME']).'/chat').'/');

在两种情况下,将 '/chat/' 修复为 '../chat/'

频道设置

在 lib 目录,导航到数据子目录并查找 channels.php 文件。假设需要三个频道,每个频道具有惟一的 ID 和名称,具体的频道设置如清单 2 所示。

清单 2. 频道设置
$channels=array()
$channels[0]='Public'
$channels[1]='123'
$channels[2]='456'

假如扩展到了 20 个频道。要节省编辑 channels.php 文件的时间,可以在 config.php 文件内将其限制为三个频道,如下所示:

$config['limitChannelList'] = array(123,456,789);

这种设置意味着只有 ID 123、456 和 789 可被用作频道,跳过了其他 17 个频道。要添加这些频道作为定制聊天频道,需要调整 lib/class/CustomAJAXChat.php 文件内的方法 getChannels()getAllChannels()。方法 getChannels() 返回包含当前用户可以访问的那些频道的一个数组。方法 getAllChannels() 返回包含全部可用频道的一个数组,不管当前用户能不能访问。

为此,需要首先向 getChannels() 方法添加如下代码:

$this->_channels = array_merge($this->_channels, 
 array('Extra_Public_Channel_1'=>123, 'Extra_Public_Channel_2'=>456, 
 'Extra_Public_Channel_3'=>789));

添加到

} return $this->_channels;

之前。

通过用 _allChannels 代替 _channels 来对 getAllChannels() 方法进行同样的处理。

编辑设置

在 data 子目录,查找 user.php 文件。请确保每个用户都具有惟一 ID 和惟一名称。此列表内的第一个用户被设置为 guest 用户,而所有 guest 用户都可以访问为此用户所设的那些频道,也都具有用户角色 AJAX_CHAT_GUEST。它们没有被分配用户名和密码。

清单 3. 默认 guest 用户
// List containing the registered chat users:
$users = array();

// Default guest user
$users[0] = array();
$users[0]['userRole'] = AJAX_CHAT_GUEST;
$users[0]['userName'] = null;
$users[0]['password'] = null;
$users[0]['channels'] = array(0);

在为注册用户、版主和管理员赋予用户角色时,不要删除此 guest 用户的用户设置。清单 4 所示的是针对管理员的示例用户设置。

清单 4. Admin 用户
$users[1] = array();
$users[1]['userRole'] = AJAX_CHAT_ADMIN;
$users[1]['userName'] = 'admin';
$users[1]['password'] = 'admin';
$users[1]['channels'] = array(0,1);

另外,还请确保更改用户名的默认设置并提供一个很好的密码。

要赋予用户 admin/moderator 权限,可在 lib/class/CustomAjaxChat.php 文件内调整 getValidLoginUserData() 方法。比如,要给某个用户 ID 为 123456 的特定用户赋予 moderator 的权限,可以将

if($userData['userID'] == 123456)
   $userData['userRole'] = AJAX_CHAT_MODERATOR;

添加在

return $userData;

之前。

进入 config.php 文件并将

$config['customModeratorList'] = array(123,456,789);

添加在

?>

之前。

然后将如下代码

if($this->getConfig('customModeratorList') && in_array($userData['userID'], 
  $this->getConfig('customModeratorList'))) {
  $userData['userRole'] = AJAX_CHAT_MODERATOR;
}

添加到 lib/class/CustomAJAXChat.php 文件内的 getValidLoginUserData() 函数的

return $userData;

之前。

上传文件

如果使用的是论坛集成版,可以将这些文件上传到服务器的文档根目录之下,比如 http://example.org/forum/chat。

假如,想在不同于 forum 的目录内使用此聊天,比如:

http://example.org/chat
http://example.org/forum

可以进入 lib/custom.php 文件并将 $phpbb_root_path = AJAX_CHAT_PATH.'../'; 更改为 $phpbb_root_path = AJAX_CHAT_PATH.'../forum/';

创建数据库表

接下来,在 chat 文件夹内创建数据库表。可以通过在服务器端执行 install.php 或使用 phpMyAdmin 来创建这些表。在用于安装脚本或 phpMyAdmin 之前,可以先编辑 chat.sql。完成之后,删除 install.php 并在 Web 站点上放置指向此 chat 文件夹的一个链接。

Ajax Chat 存在的问题及解决方法

Ajax Chat 在设计时考虑到几个不同的因素,可以提高其资源效率。首先,服务器必须执行的操作并不复杂,并且服务器查询也很简单。其次,大量工作均在客户端进行 — JavaScript 负责处理代码、执行超链接及显示定制表情符号(Emoticon)。第三,只有来自服务器的那些更新过的数据才会发送给客户机,降低了网络流量。

可能出现的一个问题是:在服务器负载很高时,再将更新了的数据从服务器推到客户机,资源的利用率就不会很高。另一个问题是默认配置存在一些安全漏洞,很容易被黑客用来实施攻击。

针对服务器过载的解决方案

减少服务器负载的一种方式是使用一个 socket 服务器。为了实现此目的,可以安装并使用一个基于 Flash(客户机端)和 Ruby(服务器端)的 socket 连接以使 chat 客户机能永久地从服务器获取更新。从服务器端推出的事件需要客户机和服务器间存在一个永久或长久的 socket 连接。而这需要一个定制 HTTP 服务器(称为 “comet”)或另一个定制 socket 服务器 — 在我看来,从服务器推出更新过的数据并不是非常有效的一种方式。

为了解决此问题,Ajax Chat 使用了一个从 JavaScript 到 Flash 的连接来建立来自客户机端的永久 socket 连接。为了运行这个 socket 服务器,必须要能够作为一种服务来运行 Ruby 脚本。要初始启动此服务,需要执行 socket 目录内的脚本文件,比如:

chmod +x server
chmod +x server.rb

其中 server 是一个 bash 脚本,server.rb 是 ruby socket 服务器脚本。

若要在其他时间开启和停止服务,可以执行 ./server start./server stop。如果停止此 chat 服务器不能奏效,可以尝试通过 -HUP 选项终止 $PID(服务的进程 ID)。

要确保服务器端聊天脚本能够通过此 socket 服务器广播消息,可以在 lib/config.php 文件内将 $config['socketServerEnabled'] 设为 true。如果正在广播消息,而同时 socket 服务器运行在另一个主机之上,那么就应该将广播客户机选项设置为此 chat 服务器 IP。

针对缺少 socket 服务器的解决方案

假设此 socket 服务器因维修的原因而关闭。此时,我们需要模拟目前暂时不可用的 socket 服务器,并且想要让来自服务器的流量保持很低并能够改进来自客户机端的响应时间。而更新调用之间的时间间隔也不存在。

我们需要配置更新调用之间的时间间隔、延迟聊天更新并设置最大的用户数量。首先,在 js/config.js 文件内将检索新的聊天消息的时间设置为 3 秒,类似如下所示:

timerRate: 3000

默认时间为 2 秒。

之后,通过在 JavaScript 文件内将 StartChatOnLoad 设为 false 来延迟聊天更新。聊天更新被延迟到载入聊天功能并开始聊天的时候。

可以类似如下所示配置 lib/config.php 文件内的最大的在线用户数:

$config['maxUsersLoggedIn'] = 80;

设置聊天内的最大用户数并不影响版主或管理员的最大数量。默认的最大数量为 100。

针对 Flash 安全性错误的解决方案

在使用 JavaScript-to-Chat 连接时,需要具备使用 Flash 创建 socket 的权限。如果 Flash 版本高于 9.0.115.0,还需要创建 socket 连接的显式权限(使用 xml-syntax)。如果使用的是较早的 Flash 版本,就会在浏览器内出现一个 Flash 安全性错误消息,即使在激活了 socket 服务器时也是如此。

一种解决方法是使用一个能在服务器端口 843 侦听连接的策略文件服务器。每当客户机试图连接到此聊天时,Flash 客户机都将会向此服务器请求策略授权。如果需要,可以下载一个 Flash 安全策略

如果在试图修复此问题时,收到了安全性错误,可以通过注释掉 js/chat.js 文件内的如下这一行来制止这些错误消息:

setTimeout('ajaxChat.addChatBotMessageToChatList(\'/error SocketSecurity\')', 0);

结束语

本文帮助您向您的环境添加了一个聊天系统。用户对能够响应系统事件(例如性能低于服务保证水平时)而弹出的开源聊天系统的需求给项目团队中试图简化工作的开发人员及其他人员带来了新的挑战。意识到并解决 Ajax Chat 设计问题以及潜在项目风险能够让您的团队没有后顾之忧。通过使用 IBM Rational® Web Developer WebSphere® 软件构建 Ajax 应用程序,再使用 IBM Rational ClearQuest 进行缺陷和应用程序跟踪,您就可以实现此目的。


相关主题

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development
ArticleID=389882
ArticleTitle=使用 Ajax 实现聊天功能
publish-date=05182009