亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Ajax 和 XML: 將 Ajax 用于聊天

系統 1800 0
了解如何使用 Asynchronous JavaScript? + XML (Ajax) 和 PHP 在 Web 應用程序中建立聊天系統。您的客戶不需要下載或安裝任何專門的即時消息通訊軟件,就能和您及其他客戶討論網站的內容。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

請訪問 Ajax 技術資源中心 ,這是有關 Ajax 編程模型信息的一站式中心,包括很多文檔、教程、論壇、blog、wiki 和新聞。任何 Ajax 的新信息都能在這里找到。

RSS 訂閱 Ajax 相關文章和教程的 RSS 提要

Web 2.0 一詞出現以來,開發人員都在說社區。不論您是否認為這有點夸大其辭,但讓用戶或讀者能夠方便地實時討論頁面主題或者銷售的產品,這一想法還是很吸引人的。但是怎么辦呢?能否在推銷產品的頁面中加入聊天,而不必讓客戶安裝任何特殊的軟件包括 Adobe Flash Player 呢?當然!實踐證明,用免費的現成工具如 PHP、MySQL、動態 HTML (DHTML)、Ajax 和 Prototype.js 庫就能完全做到。

不再羅嗦了,讓我們立即開始吧。

登錄

聊天首先要有一個身份標識。這就需要一個簡單的登錄頁,如 清單 1 所示。


清單 1. index.html

                            
<html>
<head><title>Chat Login</title></head>
<body>
<form action="chat.php" method="post">
Username: <input type="text" name="username">
<input type="submit" value="Login">
</form>
</body>
</html>

          

該頁的顯示結果如 圖 1 所示。


圖 1. 聊天登錄窗口
聊天登錄窗口

注意: 該例中需要登錄窗口是因為我希望知道誰在說話。對于您的應用程序,可能已經存在一個登錄頁面,使用自己已有的用戶名即可。




回頁首


基本的聊天系統

聊天系統實質上就是一個字符串表格,每個字符串屬于一個發言者。最簡單的模式如 清單 2 所示。


清單 2. chat.sql

                            
DROP TABLE IF EXISTS messages;

CREATE TABLE messages (
 message_id INTEGER NOT NULL AUTO_INCREMENT,
 username VARCHAR(255) NOT NULL,
 message TEXT,
 PRIMARY KEY ( message_id )
);

          

腳本中包含自動增加的消息 ID、用戶名和消息本身。如果需要,還可以向每條消息增加時間戳以記錄發送的時間。

如果需要管理不同話題的多個會話,還需要建立一個表記錄不同的話題,并在消息表中增加相關的 topic_id 。為了盡量簡化例子,我采用了最簡單的模式。

建立數據庫和加載模式使用了下列命令:

            % mysqladmin create chat
% mysql chat < chat.sql

          

根據 MySQL 服務器的設置及其安全設定和口令,命令可能略有不同。

最基本的聊天用戶界面(UI)如 清單 3 所示。


清單 3. chat.php

                            
<?php
if ( array_key_exists( 'username', $_POST ) ) {
 $_SESSION['user'] = $_POST['username'];
}
$user = $_SESSION['user'];
?>
<html>
<head><title><?php echo( $user ) ?> - Chatting</title>
<script src="prototype.js"></script>
</head>
<body>

<div id="chat" style="height:400px;overflow:auto;">
</div>

<script>
function addmessage()
{
 new Ajax.Updater( 'chat', 'add.php',
 {
 method: 'post',
 parameters: $('chatmessage').serialize(),
 onSuccess: function() {
 $('messagetext').value = '';
 }
 } );
}
</script>

<form id="chatmessage">
<textarea name="message" id="messagetext">
</textarea>
</form>

<button onclick="addmessage()">Add</button>

<script>
function getMessages()
{
 new Ajax.Updater( 'chat', 'messages.php', {
 onSuccess: function() { window.setTimeout( getMessages, 1000 ); }
 } );
}
getMessages();
</script>

</body>
</html>

          

在腳本的開始部分中,您可從登錄頁面提交的參數中獲取用戶名并存儲在會話中。然后加載 Prototype.js JavaScript 庫,它可以完成所有 Ajax 處理。

然后頁面提供了存放消息的位置。該區域由文件后面的 getMessages() JavaScript 函數填寫。

消息區域的下面是一個表單和用戶輸入消息文本的 textarea 。還有一個按鈕 Add 添加聊天消息。

頁面如 圖 2 所示。


圖 2. 簡單的聊天窗口
簡單的聊天窗口

請注意 getMessages() 函數,頁面實際上每 1000 毫秒(1 秒)輪詢一次服務器,檢查是否有新消息,并把結果輸出到頁面上方的消息區域。本文 后面 還要詳細介紹輪詢,我想首先完成基本的實現,messages.php 頁面返回當前的消息列表。該頁如 清單 4 所示。


清單 4. messages.php

                            
<table>
<?php
// Install the DB module using 'pear install DB'
require_once 'DB.php';

$db =& DB::Connect( 'mysql://root@localhost/chat', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }

$res = $db->query('SELECT * FROM messages' );
while( $res->fetchInto( $row ) )
{
?>
<tr><td><?php echo($row[1]) ?></td>
<td><?php echo($row[2]) ?></td></tr>
<?php
}
?>
</table>

          

腳本的一開始用 DB 庫連接到數據庫,這個庫可從 PEAR 下載(請參閱 參考資料 )。如果還沒有安裝這個庫,可通過下面的命令完成:

            % pear install DB

          

PEAR 安裝后,腳本可以查詢當前的消息,檢索每一行,輸出用戶名和消息文本。

最后還有 add.php 腳本,從頁面上 addmessage() 函數的 Prototype.js Ajax 代碼中調用。該腳本從會話中取得消息文本和用戶名,然后在消息表中插入新的一行。代碼如 清單 5 所示。


清單 5. add.php

                            
<?php
require_once("DB.php");

$db =& DB::Connect( 'mysql://root@localhost/chat', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }

$sth = $db->prepare( 'INSERT INTO messages VALUES ( null, ?, ? )' );
$db->execute( $sth, array( $_SESSION['user'], $_POST['message'] ) );
?>
<table>
<?php
$res = $db->query('SELECT * FROM messages' );
while( $res->fetchInto( $row ) )
{
?>
<tr><td><?php echo($row[1]) ?></td>
<td><?php echo($row[2]) ?></td></tr>
<?php
}
?>
</table>

          

add.php 腳本還返回當前的消息列表,因為原頁面中的 Ajax 代碼要從返回的 HTML 代碼更新聊天記錄。這樣用戶就能馬上看到添加到會話中的文本。

聊天系統的基本結構就是這些。下一節說明如何改進輪詢的效率。




回頁首


一點改進

這個原始的聊天系統中,頁面每秒請求一次對話的所有聊天記錄。雖然對于較短的對話影響不大,但是如果對話很長,性能問題就顯現出來了。所幸的是解決起來很簡單。每條消息都有 message_id ,這個數字自動遞增。因此,如果知道已經有了屬于某個 ID 的消息,只需要請求出現在此 ID 之后的消息就可以。這樣可以大大降低消息傳遞的數量。多數請求很可能沒有新的消息,傳遞的包就會變小。

采用效率更高的設計需要稍微修改 chat.php 頁面,如 清單 6 所示。


清單 6. chat.php(修改)

                            
<?php
if ( array_key_exists( 'username', $_POST ) ) {
 $_SESSION['user'] = $_POST['username'];
}
$user = $_SESSION['user'];
?>
<html>
<head><title><?php echo( $user ) ?> - Chatting</title>
<script src="prototype.js"></script>
</head>
<body>

<div style="height:400px;overflow:auto;">
<table id="chat">
</table>
</div>

<script>
function addmessage()
{
 new Ajax.Request( 'add.php', {
 method: 'post',
 parameters: $('chatmessage').serialize(),
 onSuccess: function( transport ) {
 $('messagetext').value = '';
 }
 } );
}
</script>

<form id="chatmessage">
<textarea name="message" id="messagetext">
</textarea>
</form>

<button onclick="addmessage()">Add</button>

<script>
var lastid = 0;
function getMessages()
{
 new Ajax.Request( 'messages.php?id='+lastid, {
 onSuccess: function( transport ) {
 var messages = transport.responseXML.getElementsByTagName( 'message' );
 for( var i = 0; i < messages.length; i++ )
 {
 var message = messages[i].firstChild.nodeValue;
 var user = messages[i].getAttribute('user');
 var id = parseInt( messages[i].getAttribute('id') );

 if ( id > lastid )
 {
 var elTR = $('chat').insertRow( -1 );
 var elTD1 = elTR.insertCell( -1 );
 elTD1.appendChild( document.createTextNode( user ) );
 var elTD2 = elTR.insertCell( -1 );
 elTD2.appendChild( document.createTextNode( message ) );

 lastid = id;
 }
 }
 window.setTimeout( getMessages, 1000 );
 }
 } );
}
getMessages();
</script>

</body>
</html>

          

不再用 “chat” <div> 標記包含所有的消息,現在改為 <table> 標記,收到新消息的時候動態地追加一行。可以看到 getMessages() 函數中的相應變化,和第一個版本相比長了一些。

新版本的 getMessages() 預期 messages.php 頁面的結果是包含新消息的 XML 塊。messages.php 增加了一個參數 id ,即頁面顯示的最后一條消息的 message_id 。一開始 ID 為 0,因而 messages.php 頁面返回所有的消息。此后則發送到目前為止顯示過的最后一條消息的 ID。

XML 響應用 onSuccess 處理程序分解成元素,每個元素使用標準 DHTML 文檔對象模型(DOM)函數添加到表格中,如 insertRow() insertCell() appendChild()

修改后的 messages.php 文件返回 XML 而不是 HTML,如 清單 7 所示。


清單 7. messages.php

                            
<?php
require_once("DB.php");

header( 'Content-type: text/xml' );

$id = 0;
if ( array_key_exists( 'id', $_GET ) ) { $id = $_GET['id']; }

$db =& DB::Connect( 'mysql://root@localhost/chat', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
?>
<messages>
<?php
$res = $db->query( 'SELECT * FROM messages WHERE message_id > ?', $id );
while( $res->fetchInto( $row ) )
{
?>
<message id="<?php echo($row[0]) ?>" user="<?php echo($row[1]) ?>">
<?php echo($row[2]) ?>
</message>
<?php
}
?>
</messages>

          

圖 3 顯示了新的改進后的版本。


圖 3. 經過優化的聊天窗口
經過優化的聊天窗口

從外觀上來說沒有什么改變。但是和原來的相比效率要高得多。




回頁首


“實時” 的秘密

如果剛接觸 Ajax 或者僅對該領域有所了解,“輪詢” 的概念可能讓您感到害怕。不幸的是,輪詢是惟一的辦法。要在客戶機和服務器之間建立連續管道,同時又不需要在兩端安裝特定軟件,尚不存在可實現此目的的跨平臺、跨瀏覽器方法。即便這樣,可能還需要對防火墻進行專門配置才行得通。因此,如果需要人人能用的一種簡便辦法,Ajax 和輪詢是惟一的可能。

但是不斷宣傳和鼓吹的 “實時” 在哪兒呢?輪詢不可能是實時的。真的如此嗎?我認為這取決于您對 實時 的定義。我過去編寫電生理學數據檢索代碼時, 實時 意味著毫秒。我相信地質學家在某些情況下把分、日甚至年看作是 實時

如果查閱 Wikipedia,即會發現人類的平均反應時間大約在 200 到 270 毫秒之間。也就是擊一次球的時間。閱讀一條消息并形成答復的時間要長得多,即使您非常投入。因此,等待聊天消息時,200 毫秒左右(可能再長一點)的時間應該足夠了。我設置為 1 秒,而且沒有感覺到不舒服。

作為 developerWorks Ajax 論壇(請參閱 參考資料 )的主持人, 輪詢 實時 的問題每月至少遇到一次。我希望對于 Ajax 來說已經揭穿了輪詢和所謂 實時 的面具。建議在考慮某種極其復雜的實時解決方案之前嘗試一下輪詢。這樣至少可以知道嘗試自定義的解決方案之前使用現成的工具能夠做什么。




回頁首


此后的工作

希望本文為您提供了一個不錯的起點,以此為基礎在您的應用程序中實現自己的聊天系統。下面是一些建議:

  • 記錄用戶: 在聊天窗口的旁邊列出目前參加會談的人員。這樣可以告訴人們誰參加了談話,什么時候來的,什么時候退出的。
  • 允許多個會談: 允許多個關于不同話題的談話同時進行。
  • 支持表情字符: :-) 這樣的字符組合翻譯成適當的笑臉圖像。
  • 使用 URL 解析: 在客戶端 JavaScript 代碼中使用正則表達式發現 URL 并轉化成超鏈接。
  • 處理 Enter 鍵: 取消 Add 按鈕,通過檢查 textarea onkeydown 事件看看用戶是否按下了 Enter 或 Return 鍵。
  • 顯示用戶輸入時間: 用戶開始輸入的時候通知服務器,會談的其他人可以看到有人在回復。這樣如果有人打字慢可以將談話結束的感覺減到最低。
  • 限制消息的大小: 保持談話順暢的另一個辦法是避免消息過長。限制 textarea 中的最大字符數 — 同樣通過捕獲 onkeydown — 有助于提高交談的速度。

這僅僅是修改上述代碼進行改進的部分想法。如果您這樣做了并且希望在社區中分享您的成果,請告訴我,我可以將其放到 下載 的源代碼中。




回頁首


結束語

我承認我不大喜歡聊天。我從未打開我的聊天客戶機。很長時間內僅使用過一次文本消息。我的聊天標識符是 idratheryouemail 。夠嚴肅的。不過我發現結合當前環境的聊天,比如本文所述的這種情況很吸引人。為什么?因為它主要集中在網站有關的主題上,可以最大限度的避免關于最近 “TomKat” 新聞這類的東拉西扯。

在您的 Web 應用程序中嘗試這段代碼。看看能否讓您的讀者和客戶進行實時交談,并通過 developerWorks Ajax 論壇告訴我效果如何。希望能給您以驚喜。

Ajax 和 XML: 將 Ajax 用于聊天


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 香蕉视频在线观看网站 | 成人看黄色大片 | 视频大全在线观看免费 | 久久福利免费视频 | 99久久香蕉国产综合影院 | 久久视频这里只精品3国产 久久视频这里只有精品 | 国产伦精品一区二区 | 一级特级欧美a毛片免费 | 国产精品久久自在自2021 | 欧美在线成人午夜影视 | 深夜福利免费在线观看 | 888米奇色狠狠俺去啦 | 色天天干| jizzz亚洲美女 | 国产成人久久久精品一区二区三区 | 一级特黄aa大片欧美小说 | 国产成人综合网亚洲欧美在线 | 亚洲精品国产第一综合99久久 | 欧美一区二区三区婷婷月色 | 9热这里只有真品 | 欧美区国产区 | 久久综合九色综合狠狠97 | 国产线路一 | 亚洲水蜜桃久久综合网站 | 逆天至尊免费看229集 | 亚洲成人免费视频在线 | 欧美久久久久久 | 奇米影音第四色 | 思思久热re6这里有精品 | 国产亚洲午夜精品a一区二区 | 亚州一级| 国产国拍亚洲精品午夜不卡17 | 亚洲一区二区欧美日韩 | 精品久久久99大香线蕉 | 四虎影视免费观看免费观看 | 欧美aⅴ | 久久这里有精品视频 | 精品一区二区三区在线观看l | 亚洲专区欧美专区 | 国产成人精品日本亚洲网站 | 久久91|