基于Ajax的即时聊天实现(服务器端代码)

一。数据库设计
KMessages表
基于Ajax的即时聊天实现(服务器端代码)

Users表
基于Ajax的即时聊天实现(服务器端代码)

这两个表构成了用户与消息之间的联系,我们的聊天系统只需要这两个表就OK啦
二。处理客户端请求
通过上一篇日志,我们分析过,客户端有两种请求,一种是发送消息(send),一种是不断地获取消息请求(get)
我们建立一个ashx文件用来处理这些请求
 1 <% @ WebHandler Language = " C# "  Class = " Message "   %>
 2
 3 using  System;
 4 using  System.Web;
 5 using  System.Web.SessionState;
 6 using  KuboLogic;
 7 using  PublicLibary;
 8
 9 public   class  Message : IHttpHandler,IRequiresSessionState  {
10    private int targetid;
11    private int userid;
12    private string lasttime;
13    private string responsestr;
14    public void ProcessRequest (HttpContext context) {
15        context.Response.ContentType = "text/plain";
16        //context.Response.Charset = "gb2312";
17        string type = ControlHelper.GetStrRequest("t");
18        userid = ControlHelper.GetIntRequest("uid");
19        if (userid == 0)//无效用户
20        {
21            responsestr = getjsonres(false"err:'不合法用户或登录超时。'");
22        }

23        else
24        {
25            switch (type)
26            {
27                case "get":
28                    targetid = ControlHelper.GetIntRequest("target");
29                    lasttime = ControlHelper.GetStrRequest("last");
30                    responsestr = getjsonres(true,
31                                             "datas:" + Messages.GetMovieMessages(userid, targetid, lasttime));
32                    break;
33                case "send":
34                    targetid = ControlHelper.GetIntRequest("target");
35
36                    string m = ControlHelper.GetStrRequest("m");
37                    //检测是否是BASE64编码
38                    if (SafeEncrpt.IsBase64Decode(m))
39                    {
40                    
41                        //string mm = context.Server.UrlDecode(SafeEncrpt.DecodeBase64("gb2312", m)); //解码后的明码
42                        //过滤非法脚本,标记等
43                        if (m.Trim()!="")
44                        {
45                            int did = Messages.addMessage(userid, targetid, m);
46                            responsestr = getjsonres(true"dbid:" + did);
47                        }

48                        else
49                        {
50                            responsestr = getjsonres(false"err:'发送的信息不能为空。'");
51                        }

52                    }

53                    else
54                    {
55                        responsestr = getjsonres(false"err:'请不要提交非法数据。'");
56                    }

57                    break;
58                case "":
59                    responsestr = getjsonres(false"err:'undefined action。'");
60                    break;
61
62            }

63        }

64        context.Response.Write("{"+responsestr+"}");
65    }

66    public string getjsonres(bool suc,string tag)
67    {
68       string  sjson = "st:{0},{1}";
69        return string.Format(sjson, suc.ToString().ToLower(), tag); 
70    }

71
72    public bool IsReusable {
73        get {
74            return false;
75        }

76    }

77
78}

在上述代码中,引用了两个类库
using
 KuboLogic;// kuboLogic命名空间,这里面有一个核心的消息逻辑处理类Message
using  PublicLibary; //公用类库,数据库访问类

kubologic/Message.cs
  1 using  System;
  2 using  System.Collections;
  3 using  System.Collections.Generic;
  4 using  System.Text;
  5 using  KuboDBFactory.BLL;
  6 using  PublicLibary;
  7 namespace  KuboLogic
  8 {
  9    /// <summary>
 10    /// Global 全局静态属性
 11    /// </summary>

 12    public class Global : System.Web.HttpApplication
 13    {
 14        // public static string users = "";
 15        // public static ArrayList Movies = new ArrayList();
 16        public static Dictionary<int, ArrayList> htMessages = new Dictionary<int, ArrayList>();
 17    }

 18    public class Messages
 19    {
 20        /// <summary>
 21        /// 添加信息到global
 22        /// </summary>
 23        /// <param name="userid">用户ID</param>
 24        /// <param name="targetid">影视ID(为负数为对用户传递)</param>
 25        /// <param name="m">发送到消息类型</param>

 26        public static int addMessage(int userid, int targetid, string m)
 27        {
 28            string sformat = "{0}|{1}|{2}|{3}"; DateTime d = DateTime.Now;
 29            KMessages k = new KMessages();//业务实体
 30            KuboDBFactory.Model.KMessages km = new KuboDBFactory.Model.KMessages();//声明模型实体
 31            km.userid = userid;
 32            km.content = m;
 33            km.stime = d;
 34            km.targetid = targetid;
 35            km.typeid = targetid > 0 ? 0 : 1;
 36            int dbid = k.Add(km);
 37            string[] sMessage = string.Format(sformat, userid, targetid, dbid, d.ToString()).Split('|');
 38            if (Global.htMessages.ContainsKey(targetid))//已经包含了此键
 39            {
 40                ArrayList s =Global.htMessages[targetid];
 41                if(s.Count==s.Capacity-1)
 42                {
 43                    ClearOldMessages(ref s);
 44                }

 45                s.Add(sMessage);
 46                Global.htMessages[targetid] = s;
 47            }

 48            else
 49            {
 50                ArrayList nArray = new ArrayList(40);//限制最大40条消息支持
 51                nArray.Add(sMessage);
 52                Global.htMessages.Add(targetid,nArray);
 53            }

 54            return dbid;
 55        }

 56        /// <summary>
 57        /// 清除过期的消息
 58        /// </summary>
 59        /// <param name="s"></param>

 60        private static void ClearOldMessages(ref ArrayList s)
 61        {
 62            for(int i=0;i<s.Count/3;i++)
 63                {
 64                    string[] arr = (string[]) s[0];
 65                    deleteMessage(int.Parse(arr[2]));
 66                    s.RemoveAt(0);
 67                }

 68            
 69        }

 70        private static void deleteTargetMessageDB(int targetid, string lasttime)
 71        {
 72            string sql = "DELETE FROM [KMessage] WHERE sTime <='{0}'";
 73            db.ExecuteSql(string.Format(sql, lasttime));
 74        }

 75        private static void deleteMessage(int messageid)
 76        {
 77            KMessages k = new KMessages();
 78            k.Delete(messageid);
 79        }

 80
 81        /// <summary>
 82        /// 得到消息列表中,不是我发送的最新消息
 83        /// </summary>
 84        /// <param name="userid"></param>
 85        /// <param name="targetid"></param>
 86        /// <param name="mStack"></param>
 87        /// <returns></returns>

 88        public static DateTime getLastDate(int userid,int targetid, ArrayList mStack)
 89        {
 90            IEnumerator ie = mStack.GetEnumerator();
 91            while(ie.MoveNext())
 92            {
 93                string[] m = (string[]) ie.Current;
 94                if(int.Parse(m[1])==targetid&&int.Parse(m[0])!=userid)
 95                {
 96                    return DateTime.Parse(m[3]);
 97                }

 98            }

 99            return DateTime.MinValue;
100        }

101
102        /// <summary>
103        /// 得到聊天室所有信息
104        /// </summary>
105        /// <param name="userid">发送者ID</param>
106        /// <param name="targetid">目标ID</param>
107        /// <param name="last">最后时间</param>
108        /// <returns></returns>

109        public static string GetMovieMessages(int userid, int targetid, string last)
110        {
111           
112            if (!Global.htMessages.ContainsKey(targetid))
113            {  ///
114                ///TODO 
115                ///如果last有值,连接数据库查询相关数据,否则返回空数组

116                return "[]";
117            }

118            StringBuilder sb = new StringBuilder();
119            ArrayList messages = Global.htMessages[targetid];//该目标的所有消息栈
120            string[] tStack = (string[])messages[messages.Count - 1];
121            //if (last != "")
122            //{
123            //    DateTime tDateLast = getLastDate(userid, targetid, messages);
124            //    if (int.Parse(tStack[0]) == userid||DateTime.Parse(last)>=tDateLast) //最后发送消息的用户ID是自己
125            //    {
126            //        return "[]";
127            //    }
128            //}
129            //Array.Reverse(messages);//按时间反向输出
130            IEnumerator ie = messages.GetEnumerator();//遍历堆栈
131            while (ie.MoveNext())
132            {
133                string[] arr = (string[])ie.Current;
134                int tid = int.Parse(arr[1].ToString());
135                DateTime d = DateTime.Parse(arr[3].ToString());//当前消息时间
136                int uid = int.Parse(arr[0].ToString());//用户ID
137                if (last != "")//有最后时间,说明这个用户的聊天记录可以被跟踪
138                {
139                    if (uid == userid || DateTime.Parse(last) >= d) continue;//我发送的消息或已接收的信息
140                }

141                sb.Append(getBasicJson(arr));
142            }

143            return "[" + sb.ToString().Trim(','+ "]";
144        }

145
146        private static string getBasicJson(string[] arr)
147        {
148            KMessages k = new KMessages();
149            KuboDBFactory.Model.KMessages km = k.GetModel(int.Parse(arr[2]));
150            if (km == nullreturn "";//数据库记录存在,已经删除
151            KuboDBFactory.Model.Users u = User.GetUser(Convert.ToInt32(km.userid));
152            string bstr = string.Format("uid:{0},uname:'{1}',tid:{2},mid:{3},m:'{4}',t:'{5}'",u.userid, u.unick, km.targetid, km.messageid,
153                                 km.content, arr[3]);
154            return "{" + bstr + "},";
155        }

156    }

157}

158

这个类是核心处理代码
我们来分析一下:
public static Dictionary<int, ArrayList> htMessages = new Dictionary<int, ArrayList>();
htMessages全局静态熟悉,相当于ASP当中的application变量,这里没有使用asp.net中的application变量是因为考虑到访问消息问题,对于
HttpApplication变量大家可以去查询相关文章,这里不多作介绍。

(未完待续)

你可能感兴趣的:(Ajax)