基于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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

这个类是核心处理代码
我们来分析一下:
public static Dictionary<int, ArrayList> htMessages = new Dictionary<int, ArrayList>();
htMessages全局静态熟悉,相当于ASP当中的application变量,这里没有使用asp.net中的application变量是因为考虑到访问消息问题,对于
HttpApplication变量大家可以去查询相关文章,这里不多作介绍。
(未完待续)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步