WCF笔记(9)群聊程序

今天,我们来做一个可以群聊的应用,就像QQ群那样,一个服务器端,N个客户端,服务器端运行后,每个客户端启动的时候会自动连接服务器生成会话,只要其中任一个客户端向服务器发送消息,服务器都会将消息群发到所有客户端。

用到的知识点:

  1. 在进程中承载WCF服务。
  2. 会话的使用。
  3. 回调。
1、还是先从服务端开始

    /// <summary>
    /// 1、定义回调接口
    /// </summary>
    public interface ICallback
    {
        [OperationContract(IsOneWay=true)]
        void SendToClients(string nickname, string message, DateTime time);
    }

    /// <summary>
    /// 2、定义服务协定
    /// </summary>
    [ServiceContract(CallbackContract=typeof(ICallback),SessionMode= SessionMode.Required )]
    public interface IService
    {
        [OperationContract(IsOneWay=true, IsInitiating=true,IsTerminating=false)]
        void Begin();
        [OperationContract(IsOneWay=true)]
        void SendMessage(string nickname, string message, DateTime time);
        [OperationContract(IsOneWay=true,IsInitiating=false,IsTerminating=true)]
        void End();
        /*Begin方法和End方法分别是启动会话和终止会话,这样每接入一个客户端连接就会实例化一个服务类;
         * 这样就可以确保每个客户端都与服务器维持一个会话。
        */
    }

    /// <summary>
    /// 3、实现服务协定
    /// </summary>
    [ServiceBehavior(IncludeExceptionDetailInFaults=true,InstanceContextMode= InstanceContextMode.PerSession)]
    public class MyService : IService
    {
        //声明一个静态的字典,存储所有客户端的会话ID所对应的回调
        public static Dictionary<string, ICallback> m_clientCallbacks = new Dictionary<string, ICallback>(); 
       
        /// <summary>
        /// 开始会话,
        /// 获取所有客户端的会话ID和回调,并将其存入字典
        /// </summary>
        public void Begin()
        {
            string sessionId = OperationContext.Current.SessionId;
            ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
            if (sessionId != null) m_clientCallbacks[sessionId] = callback;
        }

        /// <summary>
        /// 从字典中取出所有回调,
        /// 并把接收的参数传给回调方法;
        /// 在回调调用后,这些消息就会转发到所有连接的客户端,从而实现群聊。
        /// </summary>
        /// <param name="nickname">用户昵称</param>
        /// <param name="message">发送的信息</param>
        /// <param name="time">时间</param>
        public void SendMessage(string nickname, string message, DateTime time)
        {
            foreach (ICallback cb in m_clientCallbacks.Values)
            {
                if (cb != null)
                {
                    cb.SendToClients(nickname, message, time);
                }
            }
        }

        /// <summary>
        /// 结束会话,
        /// 将对应的会话ID和回调从字典中移除
        /// </summary>
        public void End()
        {
            string sessionId = OperationContext.Current.SessionId;
            if (m_clientCallbacks.ContainsKey(sessionId))
            {
                m_clientCallbacks.Remove(sessionId);
            }
        }
    }
这里在类中,声明了一个静态的Dictionary<string, ICallBack>,这是一个字典,我想大家猜到了,静态变量是基于类的,与实例无关,我们可以把它当作全局数据,在字典集合中保存所有接入客户端的回调,由于每个会话的ID是唯一的,因此,用SessionID作为Key是比较好操作的。

 //4、配置服务器
        static void Main()
        {
            //服务基地址
            Uri baseUri = new Uri("http://localhost:3000/Service");
            //声明服务器主机
            using (ServiceHost host = new ServiceHost(typeof(MyService), baseUri))
            {
                //添加绑定和终结点
                NetTcpBinding binding = new NetTcpBinding();
                host.AddServiceEndpoint(typeof(IService), binding, "net.tcp://localhost:2000/test");
                //元数据
                ServiceMetadataBehavior mb = new ServiceMetadataBehavior();
                mb.HttpGetEnabled = true;
                mb.HttpGetUrl = new Uri("http://localhost:1234/WSDL");
                host.Description.Behaviors.Add(mb);
                //启动服务
                try
                {
                    host.Open();
                    Console.WriteLine("服务已启动");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.ReadKey();
                //关闭服务
                host.Close();
            }
        }

2、实现客户端

这里我做了两个客户端,一个是winform的,一个是wpf的。我只粘贴主要代码,其余我会上传到我的资源,大家可以去那里下载

    /// <summary>
    /// 实现回调接口
    /// </summary>
    public class MyCallback : IServiceCallback
    {
        //事件
        public event EventHandler<CallbcakEventArgs> MessageReceiveEvent;

        //回调中的方法是服务器调用的,
        //在客户端要想及时侦听到该方法被调用,可以使用事件;
        //当回调方法被调用,就会触发事件.
        public void SendToClients(string nickname, string message, DateTime time)
        {
            if (MessageReceiveEvent != null)
            {
                CallbcakEventArgs args = new CallbcakEventArgs(nickname, message, time);
                MessageReceiveEvent(this,args);
            }
        }
    }

    /// <summary>
    /// 事件参数类
    /// </summary>
    public class CallbcakEventArgs:EventArgs 
    {
        private readonly string m_nickname;
        private readonly string m_message;
        private readonly DateTime m_time;
        public CallbcakEventArgs(string nickname,string message,DateTime time)
        {
            m_nickname = nickname;
            m_message = message;
            m_time = time;
        }
        public string NickName 
        {
            get { return m_nickname; }
        }
        public string Message
        {
            get { return m_message; }
        }
        public DateTime Time
        {
            get { return m_time; }
        }
    }

截图如下:



最后放上最近wcf学习的所有源码:wcf学习笔记源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值