1、一、AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍一文之中我们对AgileEAS.NET SOA中间Socket/Tcp框架进行了总体的介绍,我们知道 AgileEAS.NET SOA中间件Socket/Tcp框架是一套Socket通信的消息中间件: 二、多人在线聊天室系统 在文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答给大家实例介绍了有关于AgileEAS.NET SOA 中间
2、件Socket通信框架的简单应用之后,我们通过文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-下载配置向大家展示了一个完整成熟的.NET Socket 通信框架的应用案例,一个从在线聊天室系统,通过文章向大家讲解了如何下载和编译安案例源代码、以及如何配置服务端和客户段。 相对于简单的客户端==》服务端消息请求与应答的例子而言,在线多人聊天室系统的复杂度都要超过客户端==》服务端消息请求例子N多倍,但是限于文章篇幅的原因,我们没有在文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例
3、子-在线聊天室系统-下载配置这中为大家介绍这个案例的具体代码。 下面我将为大家介绍这个案例的关键代码及阅读、理解、修改完善所需要注意的地方。 三、关于代码编译环境及其他的地些设置 本案例的源代码在下载压缩包的Code目录之中,所有的引用AgileEAS.NET SOA 中间件平台的程序集及客户端、服务端运行所必须的文件都在下载压缩包的Publish目录之中,所有项目的编译输出路径也都是在Publish目录,也就是所有项目不管是在Debug编译环境还是在Release编译环境都是输出在Publish目录之中,有关具体的设置请看下图: 四、解决方案之中的项目说明
4、 ChatRoom解决方案之是共有ChatRoom.Entities、ChatRoom.BLL.Contracts、ChatRoom.BLL.Host、ChatRoom.Messages、ChatRoom.Socket、ChatingRoom.MainClient、ChatingRoom.UserManage共七个项目,其中: ChatRoom.Entities:是聊天室注册用启的数据存储实体,其中只包括一个实体User, 即注册用户信息。 ChatRoom.BLL.Contracts:为用户管理、登录验证、密码找回修改等功能的分布式服务定义契约,其中仅包括一个服务
5、契约定义IUserService(用户服务)。 ChatRoom.BLL.Host:为ChatRoom.BLL.Contracts所定义的服务契约的功能实现。 ChatRoom.Messages:服务端与客户端通信消息的定义,包括聊天消息、用户登录请求、登录结果、在线用户清单消息、用户上下线状态通知消息。 ChatRoom.Socket:为服务端的业务代码、包括AgileEAS.NET SOA服务进程的SocketService插件以及服务端收到客户端各种消息的消息处理器代码。 ChatingRoom.MainClient:为客户端代码、包括客户段界面以
6、及客户端收到通信消息的消息处理器代码。 五、关于SOA服务SocketService插件 如果对比AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答,细心的朋友一定会发现本案例中没有了类似Socket.Demo.Server功能的项目,而是多了ChatRoom.Socket项目。 关于这个问题就涉及到了AgileEAS.NET SOA 中间件平台的SOA服务实例及Socket框架的设计,在SOA服务实例本身被设计成为了一个可以运行WCF、WS、Socket等各吃点通信及其他应用服务的运行容器,那么我们的So
7、cket服务端也可以在此服务实例之中运行,同时在我们的AgileEAS.NET SOA中间件平台的微内核程序集EAS.MicroKernel.dll之中定义了SocketService插件的实现标准: 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: using EAS.Distributed; 6: 7: namespace EAS.Sockets 8: { 9:
8、 ///
9、
16: public interface ISocketService:IAppService
17: {
18: ///
10、Server); 23: } 24: } ISocketService接口中定义了一个初始化方法:void Initialize(ISocketServerBase socketServer),用于SOA服务实例完成对ISocketService实例的初始化,其中传入参数为一个ISocketServerBase对象,其本质的含义为SOA服务实例调用ISocketService实例对象把SOA服务实例之中的SocketServer对象做为参数传入,那么我们就可以在ISocketService对象之中针对SocketServer做一些初始化工作,其中最重要的工作是,挂
11、载与之相关的消息对象器IMessageHandler。 ChatRoom.Socket项目之中包括了一个ISocketService的实现ChatRoom.Socket.MessageService 1: using EAS.Loggers; 2: using EAS.Sockets; 3: using System; 4: using System.Collections.Generic; 5: using System.Linq; 6: using System.Text; 7: 8: namespace Cha
12、tRoom.Socket
9: {
10: ///
13、ISocketServerBase socketServer) 18: { 19: try 20: { 21: socketServer.AddHander(new ChatMessageHandler()); 22: socketServer.AddHander(new LoginMessageHandler()); 23: ChatRoomContext.Instance.SocketServer
14、 = socketServer; 24: } 25: catch (System.Exception exc) 26: { 27: Logger.Error(exc); 28: } 29: 30: socketServer.SessionStarted += socketServer_SessionStarted; 31: socketServer.SessionAba
15、ndoned += socketServer_SessionAbandoned; 32: } 33: 34: void socketServer_SessionStarted(object sender, NetSessionEventArgs e) 35: { 36: Logger.Info(string.Format("Session:{0} Started", e.Session.SessionID)); 37: } 38: 39:
16、 void socketServer_SessionAbandoned(object sender, NetSessionEventArgs e) 40: { 41: Logger.Info(string.Format("Session:{0} Abandoned", e.Session.SessionID)); 42: } 43: 44: //void socketServer_MessagerReceived(object sender, EAS.Sockets.MessageE
17、ventArgs e) 45: //{ 46: // Logger.Info(string.Format("MessagerReceived:{0}", e.Message.ToString())); 47: //} 48: 49: 50: //void socketServer_MessageSend(object sender, EAS.Sockets.MessageEventArgs e) 51: //{ 52: // Log
18、ger.Info(string.Format("MessageSend:{0}", e.Message.ToString())); 53: //} 54: 55: public void Start() 56: { 57: 58: } 59: 60: public void Stop() 61: { 62: 63: } 64: 65: #endregion 66:
19、 } 67: } 其中最重要的代码是Initialize函数之中挂载ChatMessage、LoginMessage两个消息的消息处理器代码: 1: socketServer.AddHander(new ChatMessageHandler()); 2: socketServer.AddHander(new LoginMessageHandler()); Socket插件服务的定义除了代码定义之外,还需要在AgileEAS.NET SOA 中间件有SOA服务实例配置文件之中进行定义,因为SOA服务实例程序有32位和64位版本,分别为EAS.SOA
20、Server.exe和EAS.SOA.Server.x64.exe,所以要根据自身的机器条件和自己喜欢的运行环境修改EAS.SOA.Server.exe.config或EAS.SOA.Server.x64.exe.config:
1:
2:
21、
7:
22、 23、"Value"/>
21: 24、"ChatRoom.Socket.MessageService,ChatRoom.Socket"/>
28: 25、数据访问提供者对象-->
37:
40:
41: 26、
4 27、5:
46:
49:
50:
51:
52:
53:
29、54:
57:
58:
61:
32、Socket”的SocketService。 六、注册用户数据库及Sqlite介绍 在线多人聊到室系统之中有登录、用户,那么也就必须有数据库,要存储这些注册用户的信息,为了方便这案例的使用和部署,我们选择了轻量级的Sqlite文件数据库,其特别是简单方便,对于小数据量存储非常好用,有关于Sqlite的知识请自己从网上学习,本人使用的sqlite管理工具为SQLite Expert。 注册用户表结构如下: Ø CHAT_USER(聊天室用户表) 表名 CHAT_USER 所有者 dbo 列名 数据类型 空 说明 LOGINID NVARCHAR(64
33、) N 登录ID Name NVARCHAR(64) Y 用户名 PASSWORD NVARCHAR(64) Y 密码 MAIL VARCHAR(128) Y 邮件 SafeKey NVARCHAR(64) Y 密码找回问题 SafeResult NVARCHAR(64) Y 密码找回答案 STATE BIT Y 状态 REGTIME DATETIME Y 注册时间 有关针对CHAT_USER表的数据访问使用了AgileEAS.NET SOA中间件平台的ORM及与之配套的Linq进行访问,其对应的ORM实体对象为ChatRo
34、om.Entities.User: 1: using System; 2: using System.Linq; 3: using System.ComponentModel; 4: using System.Data; 5: using EAS.Data; 6: using EAS.Data.Access; 7: using EAS.Data.ORM; 8: using EAS.Data.Linq; 9: using System.Runtime.Serialization; 10: 11: namesp
35、ace ChatRoom.Entities
12: {
13: ///
36、{ 22: this.RegTime = DateTime.Now; 23: } 24: 25: protected User(SerializationInfo info, StreamingContext context) 26: : base(info, context) 27: { 28: } 29: 30: #region O/R映射成员 31: 32: /
37、//
38、 /// 39、ary>
55: /// 密码 。
56: ///
57: [Column("PASSWORD","密码"),DataSize(64)]
58: [DisplayName("密码")]
59: public string Password
60: {
61: get;
62: set;
63: }
64:
65: /// 40、6: /// 邮件 。
67: ///
68: [Column("MAIL","邮件"),DataSize(128)]
69: [DisplayName("邮件")]
70: public string Mail
71: {
72: get;
73: set;
74: }
75:
76: /// 41、找回问题 。
78: ///
79: [Column("SafeKey","密码找回问题"),DataSize(64)]
80: [DisplayName("密码找回问题")]
81: public string SafeKey
82: {
83: get;
84: set;
85: }
86:
87: /// 42、码找回答案 。
89: ///
90: [Column("SafeResult","密码找回答案"),DataSize(64)]
91: [DisplayName("密码找回答案")]
92: public string SafeResult
93: {
94: get;
95: set;
96: }
97:
98: /// 43、 /// 状态 。
100: ///
101: [Column("STATE","状态")]
102: [DisplayName("状态")]
103: public int State
104: {
105: get;
106: set;
107: }
108:
109: /// 44、
112: [Column("REGTIME","注册时间")]
113: [DisplayName("注册时间")]
114: public DateTime RegTime
115: {
116: get;
117: set;
118: }
119:
120: #endregion
121: }
122: }
针对CHAT_USER表的用户登录、注册验证、找回密码等代码 45、的实现在ChatRoom.BLL.Host.UserService之中:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using EAS.Services;
6: using ChatRoom.Entities;
7: using EAS.Data.ORM;
8: using EAS.Data.Linq;
9:
10: namespace ChatRoom. 46、BLL
11: {
12: /// 47、 new DbEntities())
21: {
22: user.RegTime = DateTime.Now;
23: int count = db.Users.Where(p => p.LoginID == user.LoginID).Count();
24: if (count>0)
25: {
26: throw new System.Exception(s 48、tring.Format("已经存在账号为{0}的用户", user.LoginID));
27: }
28:
29: db.Users.Insert(user);
30: }
31: }
32:
33: public User UserLogin(string loginID, string password)
34: {
35: using (DbEntities db 49、 new DbEntities())
36: {
37: var v = db.Users.Where(p => p.LoginID == loginID).FirstOrDefault();
38: if (v == null)
39: {
40: throw new System.Exception(string.Format("不存在登账号称为{0}的用户", loginID));
41: }
42:
43: if (v.Password != password)
44: {
45: throw new System.Exception("密码不正确定");
46: }
47:
48: return v;
49: }
50






