服务器端是整个消息系统的中枢,类似与人类的大脑。没有他,根本无法实现客户端之间的交流,为什么呢?这也涉及到我们的系统涉及,在服务器端,每个客户端的标识数据都会在服务器端进行保存,在这种情况下,当某一个客户端请求与另外一个客户端进行交流时,我们便可以在服务器端保存的客户端列表中,找到目标客户端,并发送消息。
下面我们就一步步来实现
我们新建一个InChatter的解决方案,默认的项目可以稍后再做处理,也可是删除,我们在项目中新建一个WCF服务库(英文版本的朋友们自行参考)
在上图中,我们看到有WCF服务库、WCF服务应用程序、WCF工作流服务应用程序,我简单介绍下:
WCF服务库需要我们自己开发服务寄宿程序,而WCF服务应用程序是IIS寄宿方式的程序,是可直接运行的服务程序,.svc是服务契约文件,契约的定义和实现在.svc.cs文件中。
至于WCF工作流服务程序则是寄宿在工作流WorkFlow中的程序中的服务。
我们现在回到我们的项目中,现在我们修改实现我们的服务契约:
1 using InChatter.Service.Data; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Runtime.Serialization; 6 using System.ServiceModel; 7 using System.Text; 8 9 namespace InChatter.Service 10 { 11 [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IChatCallback), Namespace = "https://inchatter.codeplex.com/")] 12 public interface IChat 13 { 14 [OperationContract(IsOneWay=false,IsInitiating=true,IsTerminating=false)] 15 void Login(string clientId); 16 17 [OperationContract(IsOneWay=true,IsInitiating=false,IsTerminating=false)] 18 void SendMsg(InChatterMessage message); 19 20 [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)] 21 void Logout(); 22 } 23 24 public interface IChatCallback 25 { 26 [OperationContract(IsOneWay=true)] 27 void ReceiveMsg(InChatterMessage message); 28 } 29 30 }
服务契约IChat:方法的实现在服务器端,表示客户端能进行的操作,目前我们的客户端可以登录(Login)、注销(Logout)以及发送消息(SendMsg)
服务回调契约IChatCallback:方法的实现在客户端,代表服务器端能进行的操作
当客户端调用Login方法时,服务器端将初始化Session,我们这里在登录时将返回当前在线的客户端id,当客户端调用Logout时,服务器端将关闭会话,表示会话结束。而我们的消息处理就是SendMsg和ReceiveMsg。某个客户端调用SendMsg时,消息发送到服务器,服务器通过消息筛选,调用ReceiveMsg将消息发送给符合接受条件的客户端,客户端将处理接收到的消息,这个过程和SendMsg是一个完全相反的过程。那么下面我们看看我们的消息结构:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace InChatter.Service.Data 8 { 9 public class InChatterMessage 10 { 11 /// <summary> 12 /// 发送消息者ID 13 /// </summary> 14 public string SenderID { set; get; } 15 /// <summary> 16 /// 发送消息者名称 17 /// </summary> 18 public string SenderName { set; get; } 19 /// <summary> 20 /// 接收消息者id 21 /// </summary> 22 public string ReceiverID { set; get; } 23 /// <summary> 24 /// 接收消息者名称 25 /// </summary> 26 public string ReceiverName { set; get; } 27 28 /// <summary> 29 /// 消息类型:系统提醒(notice)、消息(msg)、上线提醒(logon)、下线提醒(logoff) 30 /// </summary> 31 public string Type { set; get; } 32 /// <summary> 33 /// 消息内容 34 /// </summary> 35 public string Content { set; get; } 36 /// <summary> 37 /// 消息时间 38 /// </summary> 39 public string SendTime { set; get; } 40 /// <summary> 41 /// 附加信息 42 /// </summary> 43 public string ExtendData { set; get; } 44 } 45 }
可以看到,在消息结构中,Type定义了notice、msg、logon、logoff四个消息类型,整个系统过程中的所有消息都被分为这四种形式,这是我们目前的消息结构。
现在服务端的基本框架已经有了,比较简单。下一节我们将实现IChat契约方法。