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

Users表

这两个表构成了用户与消息之间的联系,我们的聊天系统只需要这两个表就OK啦
二。处理客户端请求
通过上一篇日志,我们分析过,客户端有两种请求,一种是发送消息(send),一种是不断地获取消息请求(get)
我们建立一个ashx文件用来处理这些请求
在上述代码中,引用了两个类库
using KuboLogic;//kuboLogic命名空间,这里面有一个核心的消息逻辑处理类Message
using PublicLibary; //公用类库,数据库访问类
kubologic/Message.cs
这个类是核心处理代码
我们来分析一下:
public static Dictionary<int, ArrayList> htMessages = new Dictionary<int, ArrayList>();
htMessages全局静态熟悉,相当于ASP当中的application变量,这里没有使用asp.net中的application变量是因为考虑到访问消息问题,对于
HttpApplication变量大家可以去查询相关文章,这里不多作介绍。
(未完待续)
KMessages表

Users表

这两个表构成了用户与消息之间的联系,我们的聊天系统只需要这两个表就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
}
<%@ 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
else24
{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
else49
{50
responsestr = getjsonres(false, "err:'发送的信息不能为空。'");51
}52
}53
else54
{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 == null) return "";//数据库记录存在,已经删除
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
using System;2
using System.Collections;3
using System.Collections.Generic;4
using System.Text;5
using KuboDBFactory.BLL;6
using PublicLibary;7
namespace KuboLogic8
{9
/// <summary>10
/// Global 全局静态属性11
/// </summary>12
public class Global : System.Web.HttpApplication13
{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 Messages19
{20
/// <summary>21
/// 添加信息到global22
/// </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
else49
{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());//用户ID137
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 == null) return "";//数据库记录存在,已经删除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变量大家可以去查询相关文章,这里不多作介绍。
(未完待续)


浙公网安备 33010602011771号