登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

pcwanli的博客

nx

 
 
 

日志

 
 

jQuery+JSON开发聊天室JSON  

2011-01-16 18:47:09|  分类: jQuery |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
jQuery+JSON开发聊天室JSON
一、简介

    jQuery是一个了不起的javascript库,它可以是我们用很少的几句代码就可以创建出漂亮的页面效果。jQuery对AJAX进行了非常好的封 装,让AJAX的前台调用更加简洁跨平台。本文不对jQuery基础做更多的介绍,有兴趣者可以访问jQuery社区,得到最新的jQuery版本和相关 教程。

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习 惯,这些特性使JSON成为AJAX调用中理想的数据交换语言。PHP5.2中内置了处理JSON的两个函数:json_encode和 json_decode,可以方便地把PHP的数组和JSON字符串进行相互转换。

    本文将使用jQuery做前台的AJAX调用,后台PHP处理数据库操作,使用JSON做数据传输,完成一个简易的网页文本聊天室。该聊天室的功能包括发送文本消息、显示聊天内容、显示在线用户列表、对某个用户私聊等。

二、建表

    所有的聊天记录和在线用户都存在数据库中,这样数据库里需要建立这样两张表,建表SQL如下:

CREATE TABLE `messages` (
`id` int(10) NOT NULL auto_increment,
`sourceip` varchar(15) NOT NULL, -- 发言者的IP地址
`destip` varchar(15) NULL, -- 接收者的IP地址,如果非私聊就为NULL
`mtime` datetime NOT NULL, -- 发言时间
`content` varchar(500) NOT NULL, -- 发言内容
PRIMARY KEY  (`id`)
);
CREATE TABLE `useronline` (
`userip` varchar(15) default NULL, -- 在线用户的IP地址
`lvtime` timestamp NULL default NULL -- 该用户的上一次访问时间
);

三、页面布局

    对美工要求不那么苛刻,相关代码:

<div style="width:500px; height:500px;margin:10px auto; background-color:yellow;">
<h1 align="center">聊天室</h1>
<textarea id="content" cols="45" rows="25"></textarea>
<select id='users' size="25" style="width:100px;">
  <option>ALL</option>
</select>
对<input type="text" id="dest" size="15" value="ALL" readonly>说:
<input type="text" id="msg" size="40">
<input type="button" value="发送">
</div>

四、发言

    当用户在msg框内输入了信息后,点击“发送”按钮,或者在文本框内按回车按钮后,通过AJAX将文本内容发送到后台。在这里应该注意,发送信息和接收信息是两个独立的过程,两者之间没有关系。

    发送信息的操作相当比较简单,这里使用jQuery的ajax方法,该方法使用JSON的形式封装了提交类型、目标url、提交的数据和AJAX成功后的操作四个部分的内容。相关代码:

//因为两个地方都要调用,将发送信息的AJAX过程封装为一个函数
function sendMsg(){
$.ajax({
  type: "GET",
  url: "msgInsert.php",
  //将目标和聊天内容发送给msgInsert.php
  data: "dest="+ $("#dest").val() +"&msg="+$("#msg").val(),
  //发送成功后,将内容框清空
  success: function(v){
   $("#msg").val("");
  }
});
}
//点击"发送"按钮的时候发送
$("input:button").click(sendMsg);
//在文本框上按回车也能发送
$("#msg").keypress(function(){
if(event.keyCode == 13){ //判断按键是回车
  sendMsg();
}
});

    后台的msgInsert.php接收到数据后,将信息插入到数据库中。该部操作并不用给前台返回数据,事实上上述的前台代码也没有接收任何后台对他的反馈。简单的操作如下:

<?php
//cong worked at Tue Oct 21 06:38:45 GMT 2008
//连接数据库
mysql_connect('localhost','root','root');
mysql_select_db('chat');
mysql_query("set names utf8");
mysql_query("insert into messages values (null, '{$_SERVER['REMOTE_ADDR']}', '{$_GET['dest']}', now(), '{$_GET['msg']}')");
echo mysql_insert_id();
?>

五、接受聊天信息

    页面无刷新的接受其他用户的聊天信息,这个功能实现起来就复杂的多了。需要解决这么几个问题:

    1、 如何主动接收聊天信息。对于一个客户端来讲,永远也无法知道别人什么时候说了话,所以想实现每条信息都实时地传送到客户端是不可能的。一种替代方案是在客 户端每隔几秒钟就发出一次AJAX请求,查询一下后台是否有新的消息。这点可以通过js的setInterval()函数实现。

    2、 如何标记哪些信息对于一个客户端是未取过的信息。由于客户端的数量无非确定,每个客户端到底已经获取了哪些信息也不能确定,不能在数据库中通过加标记字段 的方式来分辨哪些已发送,哪些未发送。解决的办法是在客户端js中设置一个变量,用于保存该客户端已接收的最新的消息的id,每次发送请求时,将该id传 送给后台,只查询id号更大的消息就行了。

    3、 如何传送消息。当然是把消息封装为JSON字符串了。只不过可能新消息会有好几条,所以整个消息是一个数组,每条消息是数组中的一个子JSON对象。最终拼装成的字符串应该是如下这样一种格式:

{msgs:[
  {id:1,content:'asdf',mtime:'2008-9-2'},
  {id:2,content:'aaaa',mtime:'2008-9-2'},
  {id:3,content:'bbbb',mtime:'2008-9-2'}
]}

    OK,这几个问题都确定了,就可以进行相关的代码开发了。首先前台的请求:

//获取信息
lastid=0; //保存上次取的最后消息id
function getMsg(){
$.getJSON('msgGet.php', {'id':lastid}, function(json){
  var arr = json.msgs;      //得到对象中的信息的数组
  for( var i=0;i    lastid = arr[i].id;     //将最新的id保存
   var str = arr[i].sourceip + "(" +arr[i].mtime + ")对" + arr[i].destip +
"说:\r\n    " +arr[i].content + "\r\n";
   $("#content").text($("#content").text() + str);//信息添加到文本域后面
   //将信息滚动显示到最新
   $("#content")[0].scrollTop = $("#content")[0].scrollHeight;
  }
});
}
//每两秒从服务器取一次数据
setInterval("getMsg()", 2000);

    这里使用了jQuery的getJSON方法,该方法将前后台传递的参数都封装为JSON对象。由于从后台返回回来的JSON里存储了一个数组,所以用for进行了数组的遍历,将每条消息依次添加到文本域。

    值得一提的是为了保持文本域的滚动条一直滚动在最底下,即能显示出最新的消息,设置了文本域的scrollTop属性的值为scrollHeight属性 的值,$(“#content”)得到的是文本域的jQuery对象,不能直接访问这两个属性,需要用$("#content")[0]来得到文本域的 DOM对象。

    后台的msgGet.php文件主要接收到用户传过来的最新id,查询表,使用json_encode将每一条数据封装为一个JSON,再用字符串操作将整个将结果集封装为JSON对象数组返回。代码如下:

//查询数据,将满足条件的信息拼装为json字符串
$result = "{msgs:[";
$rs = mysql_query("select * from messages where id>{$_GET['id']}
and destip in ('ALL', '{$_SERVER['REMOTE_ADDR']}')");
while($row = mysql_fetch_assoc($rs)){
$result .= json_encode($row).',';
}
if(mysql_num_rows($rs)) //删除掉最后一个,
$result = substr($result,0,-1);
$result .= "]}";
echo $result;

六、维护在线用户列表

    由于不涉及用户的注册登陆等内容,在线用户直接就通过用户的IP地址来表示。用户只要一进入这个聊天室页面,就要把用户的IP地址记入 useronline表;一旦用户关闭聊天室,就要把用户的IP地址从表中删掉。同时,要及时的将表中的IP地址发送给每一个客户端,显示在在线用户列表 中。

    上述的问题可以简化为:在页面上每隔几秒发出请求查询一次在线用户表,在查询的同时更新本客户端IP的最后访问时间。所以前台代码为:

//获取在线用户列表
function getUsers(){
$.getJSON('userGet.php', function(json){
  $("#users")[0].length = 1; //将列表框现有的内容清空
  var arr = json.users;  //得到对象中的信息的数组
  for( var i=0;i    $("#users").append(" "+arr[i].userip+"");
  }
});
}
setInterval("getUsers()", 3000);

    后台首先维护在线用户表,然后再查询表中的ip封装为json对象返回给前台。代码:

//维护在线用户列表
//查询ip是否已经存在
$rs = mysql_query("select * from useronline
where userip='{$_SERVER['REMOTE_ADDR']}'");
if(mysql_num_rows($rs)){  //如果存在就更新最后访问时间
mysql_query("update useronline set lvtime=now()
where userip='{$_SERVER['REMOTE_ADDR']}'");
}else{      //如果不存在就新增ip
mysql_query("insert into useronline values
    ('{$_SERVER['REMOTE_ADDR']}',now())");
}
//将最后更新时间大于10秒的用户清除出在线用户表
mysql_query("delete from useronline where now()-lvtime>10");

//将最新数据返回给前台
$result = "{users:[";
$rs = mysql_query("select userip from useronline");
while($row = mysql_fetch_assoc($rs)){
$result .= json_encode($row).',';
}
if(mysql_num_rows($rs)) //删除掉最后一个,
$result = substr($result,0,-1);
$result .= "]}";
echo $result;

七、私聊

    有了前面的基础,私聊的功能就很容易实现了。只要当用户点击某个在线用户的时候,将该IP地址显示到目标IP文本框中就可以了。这样发送信息的时候就会把该目标IP一起发送出去,接受信息的时候也只有目标IP的客户端才能查询到这样的信息。

    上述功能的js代码如下:

$("#users").click(function(){
$("#dest").val($(this).val());
});

    后续的功能前面都已经实现了。
  评论这张
 
阅读(845)| 评论(0)

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018