基于Ajax的即时聊天实现(客户端)

     腾讯的网页即时聊天出现了一段时日了,开始以为腾讯是使用flash xmlsocket来建立服务器“推”消息到客户端的,但是通过对客户端代码的分析,以及使用httpwatch监视,发现也是使用按刷新率来“拉”消息。为什么不使用flash做接口呢?参考了许多网上的例子,以及各方面的反应,估计有以下几点
个人观点,欢迎指证)。我不是flash程序员
  1. flash与浏览器JS脚本交互效率不高,经常出现无响应的假死状态.
  2. flash xmlsocket使用socket协议来通信,这需要服务器端socket监听程序来支持。
    flash的安全性要求连接的主机必须在同域或配置安全性许可文件(security.xml)?,种种实现起来还是较复杂的。我不是不推行这种方式,但是对于我们这些一直没有真正包含AS脚本编程经验的同志,实现起来有点难度。
什么是ajax?大家可以去百度或Google查询下怎么定义的。总结一下就几个关键词语: 异步回调 ,后台请求
现在网上到处都是ajax技术的文章。其实说的再多,反而让你觉得神秘莫测。
一,原理分析 
目前的即时聊天技术实现,使用按设定的时间来刷新获取服务器的新消息,通常使用反复 查询数据库来实现。但是这种效率和服务器资源消耗率都不是很理想。
  如果我们在服务器内存,设定某种消息标识机制。用来标识某个客户端是否有新消息,这比反复查询数据库的效率要高的多。但是消息格式是怎样的呢?我们一步一  步来分析和实现一下。和各位朋友来一同探讨。
  这是我目前的项目所包含的一个聊天模块:
  基于Ajax的即时聊天实现(客户端)
  聊天窗口很简单,上面是内容显示区,下面是消息发送区。客户端使用javascript(jquery框架)来处理消息的发送和接收。
  如果构建这样的窗口只需要一些css布局方面的知识就足够了。我们只讲核心的实现方式
  提示:jquery框架封装了很多ajax相关的方法以及方便对DOM操作的一系列函数。
  客户端聊天代码: 
chatplugin.js


 二。消息结构

上面的客户端代码,重点在于包装消息请求,以及对服务器端响应的JSON数据进行处理。

Async函数是封装的AJAX请求函数

Async(请求地址,请求参数json结构,响应函数,内容响应格式,发送方式)

如果你对jquery有了解,其实这和JQUERYajax发送请求方式非常相似,这里进一步封装只是稍微方便一些。

1.发送消息(请求):

 1  function  sendMessage(targetid,content){
 2 
 3       var  eco = encode64(content);
 4 
 5      Async( ' chat/send/ ' ,{
 6 
 7              target:targetid,
 8 
 9              uid:User.id,
10 
11              m:eco
12 
13             }, function (r){
14 
15                     var  t = date2str( new  Date());
16 
17                     if ( ! r){showError( ' 与服务器通讯发生错误。 ' ,t); return   false ;}
18 
19                     if ( ! r.st){showError(r.err,t); return   false ;}
20 
21                    addMessage(User.nick,User.id,content,t,r.dbid, true ); // 添加消息到聊天窗口
22 
23                    clearhtml(); // 清空发送消息框的内容
24 
25                    $( " #sendbutton " ).css({disabled: false });
26 
27             }, ' json ' , ' POST ' );
28 
29  }

解释:

实际请求url /chat/send.aspx         上面的url使用urlrewrite

sendMessage(targetid,content) 函数

targetid:目标ID(可以是用户,聊天室ID) 在服务器端代码里会解释这个ID

uid:用户ID

m:使用BASE64客户端加密的消息内容

function(r){//json响应回调

       ….//这个AJAX请求发送后服务器的响应处理

}

服务器JSON消息响应:

{

st:true,

dbid:123,

err:”…..”

}

解释:

st:消息发送是否成功(true/false),dbid:消息所存储在数据库中的IDerr: 如果出现错误,服务器返回的错误信息。如果成功则留空字符串。

 

2.服务器消息的获取:

对于消息的获取,我们使用setTimeout函数启动一个“线程”隔5s去服务器端请求一次。然后处理服务器响应的内容。这里的内容可能是有新消息,或者没有任何新内容。

 1  function  getMessage(userid,targetid){
 2       // changecaption(__lastMessageTime);
 3       if (__closed){
 4          $( " #loading " ).show();
 5            return   false ;
 6       }
 7      Async( ' chat/get/ ' ,{
 8          uid:userid,
 9          target:targetid,
10          last:( typeof  __lastMessageTime == ' undefined ' ) ? '' :__lastMessageTime
11          }, function (r){
12               var  t = date2str( new  Date());
13               if ( ! r){showError( ' 网络错误或数据传输失败。 ' ,t); return   false ;}
14               if ( ! r.st){showError(r.err,t); return   false ;}
15               var  mtime = '' ;
16               if (r.datas.length > 0 ){
17                   // 按messageid顺序排序
18                  r.datas = r.datas.sort( function (a,b){
19                       return  a.mid - b.mid;
20                  });
21                  $.each(r.datas, function (i,n){
22                       var  b = true ;
23                       if (__lastMessageTime == '' ){
24                           if ($( " #msg " + n.mid).length != 0 ){
25                              b = false ;
26                          }
27                      }
28                       if (b)addMessage(n.uname,n.uid,decode64(n.m),n.t,n.mid,n.uid == User.id);
29                      mtime = n.t;
30                  });
31                   if (mtime != '' )
32                   __lastMessageTime = mtime;
33                  flashMessage();
34              }
35               // 清除LOADING
36               if ( ! $( " #loading " ).is( " :hidden " )){ __loading = false ;$( " #loading " ).hide();}
37              setTimeout( function (){getMessage(User.id,__targetid);},__constTime)
38          }, ' json ' , ' GET ' );
39  }

上面的getMessage(userid,targetid)函数 参数userid:用户IDtargetid:目标ID

请求服务器地址:chat/get.aspx

发送到服务器端的参数:

uid:userid, //用户id

target:targetid,//目标ID

last:(typeof __lastMessageTime=='undefined')?'':__lastMessageTime //最后消息接收时间(全局变量)如果第一次请求消息,则为空。

请求发送后服务器返回JSON消息格式数据

 

{

       st: true,

datas:[

{…},

{…},

{…}

]

}

服务器只返回非自身发送的消息,换句话说就是别人给我发送的消息,才返回消息数据。

同样:st表示消息的失败标志位:true表成功,false表失败

Datas:是一个数组。包含一条条的消息对象,里面的元素同样是json对象

{…}的最终结构:

 {

 mid:消息ID,

 uid:发送者用户id,

 uname:发送者用户名,

 tid:目标ID,

 m:’消息内容(使用base64加密,须解码)’,

 t:’消息发送时间

}

一个标准的消息返回示例:

{

 st:true.

datas:[

{

mid:1,uid:2,uname=’用户A’,tid:1,m:”--encode---”,t:’2009-8-7 21:38:20’

},

{

mid:2,uid:3,uname=’用户B’,tid:1,m:”---encode--”,t:’2009-8-7 21:38:22’

},

{

mid:3,uid:2,uname=’用户A’,tid:1,m:”--encode---”,t:’2009-8-7 21:38:33’

}

]

}

对服务器响应的消息,除了排序并添加到聊天内容框,还有一个比较重要的变量t变量

对于成功有效的消息,这个t时间变量表明了我最后一条接收的消息时间是t,然后将它存储在__lastMessageTime=t;全局变量中,在下次获取新消息的时候会加上这个变量作为请求参数,服务器端判断这个请求,检查内存application变量或asp.netHttpApplication静态类变量(也叫服务器全局变量)中有没有大于这个时间的消息,并且发送者不是我自己。

服务器端处理代码将在下一节提供。

在消息处理后继续隔__constTime所设定的时间,继续请求服务器端获取新内容,达到一个循环。

setTimeout(function(){getMessage(User.id,__targetid);},__constTime)

如果获取消息失败会自动停止再次请求(这里可以修改成,失败继续模式)

 

当然,安全性方面我们需要过滤客户端的一些非法代码或攻击脚本,提高服务器安全性。这里可以使用正则表达式进行过滤。具体代码在稍候提供的压缩包中。

 

客户端的消息发送格式和服务器的响应格式大体就这样子,下一篇日志中,我会给大家提供服务器端的实现,以及数据库方面的内容。

《基于AJAX的即时聊天(2)-服务器端》


你可能感兴趣的:(Ajax)