当前位置:编程学习 > C#/ASP.NET >>

传说中的WCF:群聊天程序

前面吹了不少重点知识了,为了可以较为综合地运用它们,今天,我们来做一个可以群聊的应用,就像QQ群那样,一个服务器端,N个客户端,服务器端运行后,每个客户端启动的时候会自动连接服务器生成会话,只要其中任一个客户端向服务器发送消息,服务器都会将消息群发到所有客户端。
 
我们来看看如何用WCF来取代Socket。
 
 
 
这个例子会用到以下知识点:
 
在进程中承载WCF服务。
会话的使用。
回调。
在下面说明过程中,我不会粘贴所有代码,毕竟有点长,我只放出重要部分,随后我会将源码上传到【资源】。
 
一、服务协定和回调协定。
[csharp]  
[ServiceContract(CallbackContract = typeof(ICallBack), SessionMode = SessionMode.Required)]  
public inte易做图ce IService  
{  
    [OperationContract(IsOneWay = true, IsInitiating = true, IsTerminating = false)]  
    void Begin();  
    [OperationContract(IsOneWay = true)]  
    void SendMessage(string nick, string msg, DateTime sendTime);  
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]  
    void End();  
}  
  
  
public inte易做图ce ICallBack  
{  
    [OperationContract(IsOneWay = true)]  
    void SendToClients(string nick, string msg, DateTime sendTime);  
}  
 
    [ServiceContract(CallbackContract = typeof(ICallBack), SessionMode = SessionMode.Required)]
    public inte易做图ce IService
    {
        [OperationContract(IsOneWay = true, IsInitiating = true, IsTerminating = false)]
        void Begin();
        [OperationContract(IsOneWay = true)]
        void SendMessage(string nick, string msg, DateTime sendTime);
        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]
        void End();
    }
 
 
    public inte易做图ce ICallBack
    {
        [OperationContract(IsOneWay = true)]
        void SendToClients(string nick, string msg, DateTime sendTime);
    }Begin方法和End方法分别是启动会话和终止会话,这样,每接入一个客户端连接就会实例化一个服务类(前面文章中提过了),这样就可以确保每个客户端都与服务器维持一个会话。
 
向服务器发送的消息包括用户的昵称、消息内容和发送时间。而回调协定中的方法也是这几个参数,但不同的是,服务协定是客户端调用服务器端,而回调中是服务器端调用客户端。
 
 
 
二、实现服务类。
[csharp]  
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.PerSession)]  
public class MyService : IService  
{  
    public static Dictionary<string, ICallBack> ClientCallbacks = new Dictionary<string, ICallBack>();  
    public void Begin()  
    {  
        string sessionID = OperationContext.Current.SessionId;  
        ICallBack cb = OperationContext.Current.GetCallbackChannel<ICallBack>();  
        MyService.ClientCallbacks[sessionID] = cb;  
    }  
  
    public void SendMessage(string nick, string msg, DateTime sendTime)  
    {  
        foreach (ICallBack c in MyService.ClientCallbacks.Values.ToArray())  
        {  
            if (c != null)  
            {  
                c.SendToClients(nick, msg, sendTime);  
            }  
        }  
    }  
  
    public void End()  
    {  
        string sessionID = OperationContext.Current.SessionId;  
        if (MyService.ClientCallbacks.ContainsKey(sessionID))  
        {  
            MyService.ClientCallbacks.Remove(sessionID);  
        }  
    }  
}  
 
    [ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.PerSession)]
    public class MyService : IService
    {
        public static Dictionary<string, ICallBack> ClientCallbacks = new Dictionary<string, ICallBack>();
        public void Begin()
        {
            string sessionID = OperationContext.Current.SessionId;
            ICallBack cb = OperationContext.Current.GetCallbackChannel<ICallBack>();
            MyService.ClientCallbacks[sessionID] = cb;
        }
 
        public void SendMessage(string nick, string msg, DateTime sendTime)
        {
            foreach (ICallBack c in MyService.ClientCallbacks.Values.ToArray())
            {
                if (c != null)
                {
                    c.SendToClients(nick, msg, sendTime);
                }
            }
        }
 
        public void End()
        {
            string sessionID = OperationContext.Current.SessionId;
            if (MyService.ClientCallbacks.ContainsKey(sessionID))
            {
                MyService.ClientCallbacks.Remove(sessionID);
            }
        }
    }我本来在代码中写了注释的,不过刚刚删了,我希望大家能在没有注释的前提下看懂代码。
 
在类中,声明了一个静态的Dictionary<string, ICallBack>,这是一个字典,我想大家猜到了,静态变量是基于类的,与实例无关,我们可以把它当作全局数据,在字典集合中保存所有接入客户端的回调,由于每个会话的ID是唯一的,因此,用SessionID作为Key是比较好操作的。
 
a、在Begin方法调用时,我们把传入的客户端的会话ID和回调存进字典中,在End方法调用
补充:软件开发 , C# ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,