欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript和jQuery實現(xiàn)網(wǎng)頁實時聊天的ajax長輪詢

 更新時間:2016年07月20日 16:58:22   投稿:daisy  
在做網(wǎng)頁實時聊天的時候常常需要長輪詢,本文由于采用原生的JS及AJAX,所以簡單易懂,通過這篇文章就可以建立一個簡單的聊天室程序。

介紹

大家都知道,HTTP協(xié)議是一個屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議,HTTP 協(xié)議一共有五大特點:

1、支持客戶/服務(wù)器模式;

2、簡單快速;

3、靈活;

4、無連接;

5、無狀態(tài)。

所以一次的請求都是一個單獨的事件,和前后都沒有聯(lián)系。所以我們在解決網(wǎng)頁實時聊天時就遇到一個問題,如何保證與服務(wù)器的長時間聯(lián)系,從而源源不段地獲取信息。

一直以來的方式無非有這么幾種:

1、長連接,即服務(wù)器端不斷開聯(lián)系,PHP服務(wù)器端用ob系列函數(shù)來不停的讀取輸出,但是相當(dāng)耗費服務(wù)器資源。

2、Flash socket,flash的as3語言,創(chuàng)建一個socket服務(wù)器用來處理信息。

3、輪詢,顧名思義就是不停地發(fā)送查詢消息,一有新消息立刻更新,但是會有多次無用請求。

4、長輪詢,是輪詢的升級版,需要服務(wù)器端的配合。

5、websocket,HTML5的通信功能,建立一個與服務(wù)器端的專用接口ws協(xié)議來進行通訊,兼容可能成為問題。

這篇博文總結(jié)一下用JS和JQ兩種方式(其實不同就是js和jq的實現(xiàn)),實現(xiàn)AJAX長輪詢。

長輪詢的思想:

如圖:用AJAX發(fā)送詢問信息,服務(wù)器在沒有信息要返回的時候進入無限等待。由于AJAX異步的特性,PHP在服務(wù)器端執(zhí)行等待不會影響到頁面的正常處理。一旦服務(wù)器查詢到返回信息,服務(wù)器返回信息,AJAX用回調(diào)函數(shù)處理這條信息,同時迅速再次發(fā)送一個請求等待服務(wù)器處理。

與傳統(tǒng)輪詢相比,長輪詢在服務(wù)器沒的返回信息的時候進入等待,減少了普通輪詢服務(wù)器無數(shù)次的空回復(fù)??梢赃@樣認(rèn)為,長輪詢使服務(wù)器每次的返回更有目的性,而不是盲目返回。

長輪詢的服務(wù)器端實現(xiàn):

聊天信息存儲:

數(shù)據(jù)庫設(shè)計為信息ID(msgid),發(fā)送人(sender),接收人(receiver),信息內(nèi)容(content),設(shè)置senderRead和receiverRead的目的是標(biāo)記信息是否已被讀取,讀取后改變標(biāo)記,以區(qū)別信息是否已經(jīng)被讀取。

create table msg{

  msgid int not null primary key auto_increment,

  sender char(16) not null,

  receiver char(16) not null,

  content text, //信息內(nèi)容用text類型,存儲量可達到65535字符

  senderRead tinyint enum(0,1) default 0,

  receiverRead tinyint enum(0,1) default 0 //設(shè)置一個是否已讀的flag標(biāo)記

}

PHP腳本:

 腳本的主要目的是處理來自ajax的每次詢問,ajax每次詢問就查詢一下數(shù)據(jù)庫,看有沒有新的信息,如果沒有,剛用usleep()函數(shù)等待一秒后再次查詢,直到有新信息插入數(shù)據(jù)庫并被查到,腳本返回查詢到的數(shù)據(jù),并退出無限循環(huán),結(jié)束腳本。

set_time_limit(0);//設(shè)置腳本超時時間為無限,不然在過了超時時間后腳本會自動關(guān)閉,輪詢失敗。
 $link=new mysqli("host","user","password","database");
 $search="select sender,receiver,content from msg where receiverRead=0 limit 1";//限制每次讀出一條數(shù)據(jù),便于修改其已讀flag
 $change="update chat set receiverRead=1 where receiverRead=0 limit 1";
 while (true) { //進入無限循環(huán)
     $res=$link->query($sql); //查詢結(jié)果
     if($res->num_rows!=0){ //當(dāng)有未讀信息時讀取信息
        $link->query($change);//將信息的已讀flag設(shè)為1
        $msg=$res->fetch_assoc();
        $jsonstr=json_encode($msg);//取到信息,將信息用轉(zhuǎn)碼為json格式,返回給JS
        echo $jsonstr;
        break;//輸出信息后退出while循環(huán),結(jié)束當(dāng)前腳本
     }
   usleep(1000);//如果沒有信息不會進入if塊,但會執(zhí)行一下等待1秒,防止PHP因循環(huán)假死。
 }

客戶端實現(xiàn):

客戶端的主要任務(wù)是設(shè)置一個ajax請求函數(shù),每次查詢時被調(diào)用,當(dāng)沒有信息返回時,服務(wù)器端被擱置,當(dāng)前頁面正常執(zhí)行;當(dāng)有信息返回時,函數(shù)處理返回的數(shù)據(jù),并迅速再次調(diào)用此函數(shù)發(fā)送一次請求。

用原生JS:

function link(){
 var xhr=null;//先設(shè)置xhr為空,為了輪詢時再次調(diào)用函數(shù)對xhr重用,引發(fā)錯誤
 xhr=new XMLHttpRequest();
 xhr.open('GET','serviceback.php',true);//第三個參數(shù)一定要設(shè)置為true,異步不阻塞,不會影響到后面JS的執(zhí)行。
 xhr.send();
 xhr.onreadystatechange=function(){
     if (xhr.readyState==4) { 嚴(yán)密也可加使用(xhr.readyState==4 && xhr.status ==200)限定服務(wù)器響應(yīng)碼為200時才進行處理。
        if(xhr.responseText!=''){
           process... //服務(wù)器端返回信息,且返回信息不為空,則開始處理返回信息。
        }
    setTimeout("link()",300);
//遞歸再次調(diào)用link()函數(shù),用setTimeOut()設(shè)置延時是因為服務(wù)器端進行sql操作時會耗時,當(dāng)有新信息時,在服務(wù)器將要置已讀flag為1還未成功時,AJAX可能已經(jīng)又發(fā)出多條查詢信息了,會導(dǎo)致一條信息多次返回。
    }
 };
}

用jQuery插件實現(xiàn):

var link={           //jQuery的AJAX執(zhí)行的配置對象
  type:"GET",      //設(shè)置請求方式,默認(rèn)為GET,
  async:true,      //設(shè)置是否異步,默認(rèn)為異步
  url:"customback.php",
  dataType:"json",    //設(shè)置期望的返回格式,因服務(wù)器返回json格式,這里將數(shù)據(jù)作為json格式對待
  success:function (msg){
      process...
     setTimeout("link()",300);
  }              //成功時的回調(diào)函數(shù),處理返回數(shù)據(jù),并且延時建立新的請求連接
}
$.ajax(link);          //執(zhí)行ajax請求。
]

程序擴充:

添加發(fā)送聊天窗口:

新建一個函數(shù)用來處理ajax的POST請求,用ajax將發(fā)信人,每次發(fā)送的信息,收信人發(fā)送到服務(wù)器端,并設(shè)置一個單獨的PHP腳本處理信息,將信息插入數(shù)據(jù)庫。

需要注意的是,用JS原生實現(xiàn)POST請求發(fā)送信息時,要設(shè)置ajax對象的HTTP頭,模擬表單提交的操作:

xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");

聊天室消息處理:

為了防止每次都查詢到全部信息,我們對數(shù)據(jù)庫的查詢操作更改一下,設(shè)置idflag=0,每次查詢后,設(shè)置idflag為查詢到的數(shù)據(jù)的id,查詢時我們查詢比idflag大的ID,即,新添加進去的信息。

好了,本文到此就結(jié)束了,利用本文的示例代碼一個簡單的聊天室程序就做好了,感興趣的可以快快實踐下了。

相關(guān)文章

最新評論