正文

web聊天程序,Ajax实现即时通讯2007-12-03 16:39:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/sgpro/31254.html

分享到:

  Ajax 是用javascript和DOM,XML实现的web客户端与服务器端的异步通讯技术。 不是什么新东西,老技术,新面孔而已。 对于构建类似桌面应用的web程序来说,Ajax无疑是有效的工具, 处理强交互性做得很突出。 Google是Ajax的先行者, 大名鼎鼎的Google Map则是Ajax的优秀作品。 相信Ajax的广泛运用将进一步改变web程序的面孔,同时过去被认为只有桌面程序更加能满足要求的构架方案如今Ajax可以成为另一种不错的选择。桌面程序则再次面临市场萎缩,与此同时b/s在继续拓宽其领地。  Ajax不是什么新技术, 只要客户端的浏览器支持javascript,支持dom就能完成Ajax的核心工作之一, 而服务器端代码你可以选择3p技术的任何一种, 是极其自由的。以前的web聊天程序, 你或许要常常刷新页面来获知你是否有了新的消息,而一次刷新则意味着一次和页面载入,这显然不符合即时通讯的要求,在这里Ajax则有了发挥的空间,这是我为什么选择它的原因。  如果你熟悉Ajax, 请允许我上面说了这么多废话,因为我无法保证每个读者都熟悉它。当然不乏精通人士,敬请纠正我的错误,如果存在的话。 现在我将发布我的Ajax作品。 请不要误以为我在炫耀什么,这并不是什么高级的作品,事实上我只是想发布它,因为很长时间我的blog没有更新了,当然如果我的行为对你的进步产生了影响,那将会使我感觉到快乐。最后要说的是, 著作权,中国人不太重视这个, 我想说的是,不管这个作品品质如何,只要它是出自某个人辛苦的劳作而且未将它授权给别人,那它就属于作者, 你需要适当限制发生作者不愿看到的行为,特别是商业目的。在这个实例当中客户端我使用了ms的浏览器, 服务器端则采用ms的 jscript一共7个程序文件Ajax.js   :  Ajax程序的中心库,我希望这是一个通用框架的核心组成部分AjaxApp.js : 本程序响应服务器异步通讯的代码, 负责本程序客户端的大部分工作frmInpCheck.js: 表单输入的控制模块pageCtl.js: 页面元素的控制模块, 集中体现Ajax中DOM的运用util.js: 其他工具模块web-sgn.asp: 客户端页面代码,利用Ajax交互的页面web-server-sgn.asp: 服务器的后端代码,Ajax通讯的服务端还需指出的是 Ajax名义上是需要利用xml格式进行数据双端交付的。本程序并没有体现这点, 但丝毫未影响Ajax的正常工作,我采用了某种常规的替代方法。 访问体验本程序最新 v1.4 版: http://www.v8v.com.cn/_sgpro/web-sgn/web-sgn.asp 运行效果图:    v1.42 效果图   以下是v1.0的全部源代码://Copyright (C) 2007-11 sgpro//程序:Ajax.js //建立xmlHttpRequest对象  var globalXmlHttp = false;  function CreateXMLHttp() {    try   {   //alert("create activeX");   globalXmlHttp = new ActiveXObject("Msxml2.XMLHTTP");  }   catch (e)   {   try    {        globalXmlHttp = new ActiveXObject("Microsoft.XMLHTTP");     }      catch (e2)      {        globalXmlHttp = false;     }    }  //alert("create activeX success");  return globalXmlHttp; }  function nonAjaxTrans() {  return typeof(globalXmlHttp) == 'boolean' &&       globalXmlHttp == false; }   //Ajax传送, text方式 function AjaxTransText(sUrl, funcCallClient) {  if (nonAjaxTrans())  {      if ( typeof(CreateXMLHttp()) != 'object')   {    return false;   }  }    globalXmlHttp.open("GET", sUrl, true);  globalXmlHttp.onreadystatechange  = funcCallClient;   globalXmlHttp.send(null); }  //Ajax传送, xml方式 function AjaxTransXML(sUrl, xml, funcCallClient) {  alert("sUrl:" + sUrl + "\nxml:" + xml + "\nfunc:" + funcCallClient);  if (nonAjaxTrans())  {      if ( typeof(CreateXMLHttp()) != 'object')   {    return false;   }  }    globalXmlHttp.open("POST", sUrl, true);  globalXmlHttp.setRequestHeader("Content-Type", "text/xml");  globalXmlHttp.onreadystatechange  = funcCallClient;  globalXmlHttp.send(xml); }   //获取Ajax连接对象的状态 function getAjaxTransState() {  if (!nonAjaxTrans())  {   return globalXmlHttp.readyState;  }  return false; }  function ajaxTransReady() {  if (!nonAjaxTrans()) {   if (globalXmlHttp.readyState == 4 &&       globalXmlHttp.status == 200 ) {          return true;         }        }        return false;   }  //获取Ajax返回文本  function getAjaxTransResultText() {    if (ajaxTransReady()) {   //alert(globalXmlHttp.responseText);         return globalXmlHttp.responseText;        } }    //获取Ajax返回xml  function getAjaxTransResultXML() {  if (ajaxTransReady()) {         return globalXmlHttp.responseXML;        }  }  function cleanAjax() {  globalXmlHttp = false; } //程序:AjaxApp.js var     globalUrl = "web-server-sgn.asp"; var     globalSelectUser;  function AjaxTextDispatch(procName) {  var ajaxUrl;  var ajaxHandle;    //alert(procName);  ajaxUrl = globalUrl + "?func=" + procName;    switch (procName ) {      case "logout":    if (frmLogin.username.value == "") {     return;    }           ajaxUrl = ajaxUrl + "&username=" + frmLogin.username.value;    ajaxHandle = logout;   break;      case "login":    res.innerText='请稍候...';     if (!checkNotNull(frmLogin)) {     return false;    }       ajaxUrl = ajaxUrl + "&username=" + frmLogin.username.value +         "&password=" + frmLogin.password.value;         ajaxHandle = login;      break;   case "register":    if (!checkNotNull(frmLogin))    {     return false;    }    document.getElementById("res").innerText='请稍候...';        ajaxUrl = ajaxUrl +  "&username=" + frmLogin.username.value +               "&password=" + frmLogin.password.value;     ajaxHandle = register;       break;      case "getUserList":    ajaxHandle = getUserList;   break;      case "receiveMessage":             ajaxUrl = ajaxUrl + "&FromUser=" + frmMessage.ToUser.value +                                  "&ToUser=" + frmMessage.FromUser.value;        ajaxHandle = receiveMessage;   break;    case "sendMessage":    if (!checkNotNull(frmMessage))    {     return false;    }        if (frmMessage.ToUser.value=="")    {     alert("请选择联系人...");     UserListBlock.UserList.focus();     return false;    }        ajaxUrl = ajaxUrl + "&FromUser=" + frmMessage.FromUser.value +        "&ToUser=" + frmMessage.ToUser.value +        "&Message=" + frmMessage.Message.value;    ajaxHandle = sendMessage;          break;     }    //alert(ajaxUrl);  AjaxTransText(ajaxUrl, ajaxHandle); }  function login() {     if (!ajaxTransReady()) {   return;  }     var ret = getAjaxTransResultText();   if (ret == "")  {   ret="连接失败";  }   if (ret == "False")  {   ret = "用户或密码无效";   alert(ret);  }  else  {   alert("登陆成功");   document.frmLogin.style.display = "none";   UserListBlock.style.display="block";   document.frmMessage.style.display = "block";   document.frmMessage.FromUser.value = frmLogin.username.value;       AjaxTextDispatch('getUserList');   freshInputing();   ListenMessage();     }         document.getElementById("res").innerHTML ="<font color=red> " + ret + "</font>";    return;  }   function getUserList() {   //var nodesNum = frmMessage.ToUser.childNodes.length;  //alert("Nodes:" + frmMessage.ToUser.childNodes.length);  //for (var i=0; i < nodesNum - 1; i++)  //{  // document.frmMessage.ToUser.removeChild(frmMessage.ToUser.childNodes[i]);  //}    if (!ajaxTransReady()) {   return;  }     globalSelectUser = UserListBlock.UserList.value;    UserListBlock.UserList.innerHTML = "";            var ret = getAjaxTransResultText();    var   str = new String(ret);  var   uls = str.split("<br>");    var  utext="";    for( var i =0; i < uls.length-1;  i++)  {   var op = document.createElement("option");   var str2 = new String(uls[i]);      op.value=str2.split("|")[0];   op.innerHTML = str2.split("|")[0];   op.innerText = str2.split("|")[0] + (str2.split("|")[1] == "true"? " (联机)":" (脱机)");   op.statu =  str2.split("|")[1];      UserListBlock.UserList.appendChild(op);   }  RefreshOnline();  }   function register() {    if (!ajaxTransReady()) {   return;  }      var ret=getAjaxTransResultText();   if (ret == "")  {   ret="连接失败";  }   if (ret == "False")  {   ret = "The user '" + frmLogin.username.value + "' had been used";   alert(ret);  }  else  {   ret = "Register success";      if (confirm("注册成功,现在就登录吗?") == true)   {    login();   }              }  document.getElementById("res").innerHTML ="<font color=red> " + ret + "</font>";    return;  }  function logout() {  if (!ajaxTransReady()) {   return;  }     var ret=getAjaxTransResultText();    if (ret == "")  {   ret="连接失败";  }   if (ret == "False")  {   ret = frmLogin.username.value + " 未能成功注销!";        }  else  {   ret = frmLogin.username.value + " 已经退出";  } }    function receiveMessage() {   if (!ajaxTransReady()) {   return;  }       var ret=getAjaxTransResultText();   //alert(ret);    if (ret == "")    {     ret="连接失败";    }     if (ret == "false")    {     window.title= "无消息";     res.innerHTML="<font color=red> " + ret + "</font>";       }      else      {       var str = new String(ret);              var strArr = str.split("<br>");       var listt = "";       //alert(strArr);            for ( i =  0; i  < strArr.length-1; i++)     {      var str2 = new String(strArr[i]);      t = str2.split("|")[0]; //时间      f = str2.split("|")[1]; //from    m = str2.split("|")[2]; //msg        //listt = t + " " + f + "说:\r\n  " + m + "\r\n";    listt = f + " 说 (" + t + ")\r\n  " + m + "\r\n";    frmMessage.panel.value = frmMessage.panel.value + listt;    scrollToPanelBottom();       }  }    AjaxTextDispatch('getUserList');  timerOut=window.setTimeout("AjaxTextDispatch('receiveMessage')",1000);  }    function sendMessage() {    if (!ajaxTransReady()) {   return;  }    var ret=getAjaxTransResultText();  if (ret == "")  {   ret="连接失败";  }   if (ret == "False")  {   ret = "发送失败";   res.innerHTML="<font color=red> " + ret + "</font>";     }  else  {   var msgtxt = frmMessage.FromUser.value + " 说 (" +  GetNow() + ") \r\n  " +                frmMessage.Message.value + "\r\n";    frmMessage.panel.value = frmMessage.panel.value + msgtxt;  }  scrollToPanelBottom();  frmMessage.Message.value = "";  frmMessage.Message.focus();      } //程序:pageCtl.js function ListenMessage() {  window.ListenTimer = setTimeout("AjaxTextDispatch('receiveMessage')",1000); }  function selectUser() {  frmMessage.ToUser.value= UserListBlock.UserList.value;    UserListBlock.style.display = "block";  frmMessage.style.display = "block";      frmMessage.FromUser.disabled = false;     if ( frmMessage.FromUser.value == frmMessage.ToUser.value)  {   document.getElementById("tip").innerHTML = "<font color='red'>请问" + frmMessage.FromUser.value + "同志: <br>您不觉得和自己聊天是对您的智商的一种侮辱吗?<br>我们试图纠正您的失误并且作出了某种限制。</font>";   frmMessage.Message.disabled=true;     }  else  {   document.getElementById("tip").innerText=   frmMessage.FromUser.value + " 与 " + frmMessage.ToUser.value + " 聊天中"   frmMessage.Message.disabled=false;   frmMessage.Message.focus();  } }  function  RefreshOnline() {   for (var i=0; i < UserListBlock.UserList.childNodes.length; i++)  {   var op = UserListBlock.UserList.childNodes[i];       if (op.value == globalSelectUser)   {         op.selected="true";    break;   }  } }  function scrollToPanelBottom() {   frmMessage.panel.scrollTop=frmMessage.panel.scrollHeight; }  function ChangeGlobalValue() {   globalSelectUser = UserListBlock.UserList.value; }  function sendByShortCut() {  if (event.keyCode == 13)  {    document.getElementById("btnSend").click();      return false;   }  else  {   freshInputing();   return true;  }  }   function freshInputing() {  var Reg = new RegExp("\r\n", "g");  frmMessage.Message.value = frmMessage.Message.value.replace(Reg, "");     document.getElementById("btnSend").disabled= (frmMessage.Message.value == "");   } //程序:util.js function GetNow() {     return FormatDateTime(""); }  function FormatDateTime(date) {  var  dat;    if (date == "" || date == null)  {   dat = new Date();  }  else  {   dat = new Date(date);  }    var  y = dat.getYear();  var  m = parseInt(dat.getMonth())+1  var  d = dat.getDate();  var  h = dat.getHours();  var  min = dat.getMinutes();  var  s = dat.getSeconds();   var  strDateTime =  y + "-" + m + "-" + d + " " + h + ":" + min + ":" + s;    return strDateTime;   }//程序:web-sgn.asp<%@language='javascript'%><html> <head> <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312">  <title>web sgn</title> </head>  <script src="util.js"></script> <script src="frmInpCheck.js"></script> <script src="pageCtl.js"></script>  <script src="Ajax.js"></script> <script src="AjaxApp.js"></script>  <script language="javascript"> </script>  <body onunload="AjaxTextDispatch('logout')"> <table align="center" valign="top" bgcolor="#dddddd" border=1 cellspacing="0" cellpadding="0"> <tr>   <td>  <form  name="frmLogin" id="frmLogin" action="web-server-sgn.asp" method="post" onsubmit="return checkNotNull(this);">  用户:<input type="text" name="u" id="username"  NotNull="true" tag="用户名"><br>  密码:<input type="password" name="p" id="password"  NotNull="true" tag="密码"><br>    <button onclick="AjaxTextDispatch('login')" >登陆</button>  <button onclick="AjaxTextDispatch('register')" >注册</button>   <input type="submit" value="同步登陆">   <input type="hidden" id="func" name="func" value="login">   <div id="res" name="res"></div>  </form>   </td> </tr> <tr>   <td valign="top" align="center">    <form id="UserListBlock" name="UserListBlock" style="display:none;">                 <br><center><div id="tip" style="font-size:28;font-family:'黑体';">                 双击选择下面的联系人聊天</div></center><br>         <select name="UserList" id="UserList"  size="8" MULTIPLE   style="width:200;border:inset 2px;"     ondblclick="selectUser()"   onclick="ChangeGlobalValue()"></select>  </form>   </td> </tr> <tr>   <td>     <form  name="frmMessage"   id="frmMessage"   action="web-server-sgn.asp" method="post"  style="display:none;"   onsubmit="return checkNotNull(this);">           <textarea  name="panel" id="panel"         ="scrollToPanelBottom()"         style="font-size:12;font-weight:1;color:#ffff33;width:660;border:inset 2px ; background-color : #7777ff; text-left-padding:10px;"          rows="20"  readonly NotNull="false" tag="消息"></textarea><br>           <textarea name="Message"   id="Message" width="570"  NotNull="true" tag="消息" disabled="true"  rows="4" cols="70" multiple   style="border:inset 1px #777777;"  onkeydown="sendByShortCut()"  onkeyup="freshInputing()"></textarea>  <button id="btnSend" onclick="AjaxTextDispatch('sendMessage')" style="width:70;height:70;" >发送消息</button>  <input type="button" value=" 注  销 "   onclick="window.location=location.href;" style="width:70;height:70;border: dashed 1px;">  <input type="hidden" id="func" name="func" value="sendMessage">  <input type="hidden" id="FromUser" name="FromUser" value="">    <input type="hidden" id="ToUser" name="ToUser" >    <!--<div id="online"></div>-->  </form>    </td> </tr>     </table>    </body></html>//程序:Web-server-sgn.asp<%@language="javascript"%> <%  function GetNow() {     return FormatDateTime(""); }  function FormatDateTime(date) {  var  dat;    if (date == "" || date == null)  {   dat = new Date();  }  else  {   dat = new Date(date);  }    var  y = dat.getYear();  var  m = parseInt(dat.getMonth())+1  var  d = dat.getDate();  var  h = dat.getHours();  var  min = dat.getMinutes();  var  s = dat.getSeconds();   var  strDateTime =  y + "-" + m + "-" + d + " " + h + ":" + min + ":" + s;    return strDateTime;   }   var conn;  function DbConnect(strPath, strUser, strPass) {    try  {   var connstr =       "Provider=Microsoft.Jet.OLEDB.4.0;" +    "Data Source=" + Server.MapPath(strPath) + ";" +    "User Id="     + strUser +                 ";" +   "Password="    + strPass +                 ";"      conn = Server.CreateObject("ADODB.Connection");   conn.Open(connstr);   return true;  }  catch (e)  {        Response.Write("<center><h1><b><font color = red>Db Connection Error:" + connstr + "</h3></font></b>");     return false;    } }  function  DbExecute(StrSqlStatement) {    try  {      var rs = conn.Execute(StrSqlStatement);  }    catch ( e)   {           Response.Write("<center><h1><b><font color = red>Db Execute Error:"+e.message + "<br>");      Response.Write(StrSqlStatement + "</h3></font></b>");     debugger;         return false;       }  return rs; }  function  DbCollect() {   try  {      var rs = conn.close();  }    catch ( e)   {            Response.Write("<center><h1><b><font color = red>:Db Collect Error: "+e.message + "<br>");     Response.End();       }  return rs; }   function sendMessage(strDateTime, strFromUser, strToUser, strMessage) {  if (conn == undefined)  {   DbConnect(Server.MapPath("chartdb.mdb"), "","");  }    var strSql = " INSERT INTO Message(msgtime, userfrom, userto, msgtext, hasread) VALUES( '" +         strDateTime + "','" +         strFromUser + "','" +         strToUser + "', '" +        strMessage + "'," +         " false) ";          var ret = DbExecute(strSql);    return typeof(ret) != 'False';   }  function receiveMessage(strFromUser, strToUser) {    if (conn == undefined)  {   DbConnect(Server.MapPath("chartdb.mdb"), "","");  }    var ret = "";    var strWhere = "  WHERE userto = '" + strToUser +           "' AND hasread = false"  var strSql = " SELECT * FROM Message " + strWhere;             var rs= DbExecute(strSql);   while (!rs.Eof)  {   ret = ret + FormatDateTime(rs("msgtime")) + "|" + rs("userfrom") + "|" + rs("msgtext");   ret = ret + "<br>";   rs.MoveNext();  }        rs.close();   var strUpd = "UPDATE Message SET hasread = true " + strWhere;    DbExecute(strUpd);    return ret; }  function register(strUserName, strPassword) {  if (VerifyUser(strUserName, strPassword, false))  {   return false;  }       var strSql = " INSERT INTO [user](username, [password], online) VALUES ( '" +         strUserName + "','" + strPassword + "', false) ";          var ret = DbExecute(strSql);      return typeof(ret) != 'False'; }  function getUserList() {  if (conn == undefined)  {   DbConnect(Server.MapPath("chartdb.mdb"), "","");  }    var strSql = " SELECT * FROM [user] order by online, [username]";            var rs= DbExecute(strSql);    return rs;  }  function VerifyUser(strUserName, strPassword, blnCheckPassword) {  if (conn == undefined)  {   DbConnect(Server.MapPath("chartdb.mdb"), "","");  }    var strSql = " SELECT * FROM [user] WHERE username='" + strUserName + "'"    if (blnCheckPassword == true)  {    strSql = strSql + " AND [password]='" + strPassword + "'";  }              var rs= DbExecute(strSql);    return !rs.Eof;  }  function login(strUserName, strPassword) {  if (VerifyUser(strUserName, strPassword, true))  {   return setOnlineStatus(strUserName, true);  }  else  {   return false;   }  }  function logout(strUserName) {  if (conn == undefined)  {   DbConnect(Server.MapPath("chartdb.mdb"), "","");  }    return setOnlineStatus(strUserName, false); }  function setOnlineStatus(strUserName, blnStatus) {  if (conn == undefined)  {   DbConnect(Server.MapPath("chartdb.mdb"), "","");  }      var strUpd = "UPDATE [user] SET online = " + blnStatus + " WHERE username='" + strUserName + "'";    var ret = DbExecute(strUpd);    return typeof(ret) != 'False'; }   var func = Request("func");  if (func == undefined || func== Request("null")) {  func=""; }  Response.charset = "GB2312";   DbConnect("chartdb.mdb", "",""); if (func == "sendMessage") {  var result = sendMessage(GetNow(), Request("FromUser"),       Request("ToUser"), Request("Message"));  Response.write(result); }  else if (func == "receiveMessage") {  var rs = receiveMessage(Request("FromUser"), Request("ToUser"));  if (rs=="")  {   rs = "false";  }  Response.write(rs); } else if (func == "getUserList") {  var rsu = getUserList();    if (typeof(rsu) != false)  {   while (!rsu.Eof)   {    Response.write(rsu("username") + "|" + rsu("online"));        Response.write("<br>");    rsu.MoveNext();   }  }  rsu.close();   }  else if (func == "login") {  var rs = login(Request("username"), Request("password"));    Response.write(rs);   }  else if (func == "logout") {  var rs = logout(Request("username"));    Response.write(rs); } else if (func == "register") {  var rs = register(Request("username"), Request("password"));    Response.write(rs); }  else {  Response.write("Parameters Error func='" +  func +"'"); }   DbCollect();%> //Copyright (C) 2007-11 sgpro 版本陆续升级中。。。 版本履历 v1.0功能: 注册,登录,注销,发送消息,接受消息,声音提示,实时更新用户列表和状态 v1.1功能: (新增)加载消息历史记录 v1.2功能: (新增)收发即时动作(如***正在输入消息)(新增)支持可视化元素传输如图片,链接,多媒体等。(修改)Ajax内核采用同步请求组 v1.21功能: (修改)Ajax内核增强请求队列组 (修改)Ajax错误处理能力(修改)用户表修改,增强用户信息处理(登录次数,登录ip等) v1.3功能: (新增) 收发闪屏震动(新增) 收发表情(新增) 字体选择,字体颜色,大小,样式编辑(新增) 掉线自动重连 (新增) 工具箱(修改)Ajax内核增强(修改)更改页面布局,页面样式  v1.4功能: (新增)好友管理(发出请求,处理验证,添加好友) (修改)Ajax内核增强请求队列错误的滞后排空 (修改) Ajax请求加入时间戳标识,排除重复取缓存问题

阅读(8124) | 评论(16)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册