在上篇文章中介绍了一下WCF中的客户端到服务器端的单向通知,在实际应用中,还经常使用服务器端到客户端的单向通知。例如,在聊天室里,我们需要把某人的发言广播给每一个人。对于这种单向通知,我们一般称为回调。本文就以一个简单的聊天室为例,介绍一下如何实现回调。

1. 定义一个回调接口

interface IMessageCallback
    {
        [OperationContract(IsOneWay = true)]
        void OnMessageAdded(string message, DateTime timestamp);
    }

这个接口并不是服务,因此没有ServiceContract标志,但其回调函数形式需要被公布,因此接口函数有OperationContract标志,另外,这个也是一个单向通知,因此有IsOneWay = true设置(注:这里的IsOneWay不是必须的,可以获取回调函数的返回值的)。

2. 在服务契约上加上回调通知接口声明

[ServiceContract(CallbackContract = typeof(IMessageCallback))]
    public interface IService1
    {
        [OperationContract]
        void AddMessage(string message);

[OperationContract]
        void Subscribe();

[OperationContract]
        void Unsubscribe();
    }

除了客户端上报消息的接口外,这里也加了两个接口函数Subscribe和Unsubscribe,用来注册回调和删除回调,实现了一个典型的观察者模式。(PS:这两个接口并不是必须的,主要是为了方便演示回调的实现过程)

3. 实现回调

接口声明完成后,给了一个简单的实现(这个只是示例代码,线程安全,最佳实践神马的都没有考虑,不要用于实际项目中)。

public class Service1 : IService1
    {
        static List<IMessageCallback> subscribers = new List<IMessageCallback>();

public void AddMessage(string message)
        {
            subscribers.ForEach(callback =>
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                    callback.OnMessageAdded(message, DateTime.Now);
                else
                    subscribers.Remove(callback);
            });
        }

public void Subscribe()
        {
            var callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
            subscribers.Add(callback);
        }

public void Unsubscribe()
        {
            var callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
            subscribers.Remove(callback);
        }
    }

从上述代码中可以发现,回调的基本使用方式如下:

  • 从OperationContext.GetCallbackChannel中获取回调通道对象,该对象实现了回调接口和ICommunicationObject接口。
  • 根据IcommunicationObject.State属性查看其是否可用,也可以注册IcommunicationObject. Closed事件主动响应客户端退出。
  • 调用回调对象的回调函数接口即可实现回调通知
4. 服务器端配置

编译并运行上述服务后,会发现一个服务无法启动的错误。

原因说得很清楚,要使用CallbackContract,则需要底层协议支持双工(因为需要从服务器端主动通知客户端)。但目前使用的BasicHttpBinding由于是基于Http协议,不支持双工(另外一个基于Http协议的WSHttpBinding也不支持双工),要改成支持双工的协议。目前WCF中支持双工的协议有如下几种:

  • 基于TCP协议的NetTcpBinding
  • 基于管道的NetNamedPipeBinding
  • 基于Http协议的wsDualHttpBinding,虽然Http协议本身不支持双工,但是wsDualHttpBinding通过创建两个不同方向的Http连接来实现了双向传输。

为了简单,我这里就改成了wsDualHttpBinding。

5. 实现客户端代码

由于WCF测试客户端不支持回调的测试,因此这里我们就需要手动实现客户端代码:

static void Main(string[] args)
        {
            var context = new System.ServiceModel.InstanceContext(new Callback());
            var client = new WcfClient.Service.Service1Client(context);

client.Subscribe();
            while (true)
            {
                var input = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(input))
                    break;

client.AddMessage(input);
            }

client.Unsubscribe();
            client.Close();
        }

class Callback:IService1Callback
        {
            public void OnMessageAdded(string message, DateTime timestamp)
            {
                Console.WriteLine(">>> Receive Message {0} {1}", message, timestamp);
            }
        }

编写这个代码时就会发现:现在Client的构造函数需要传入一个参数了,在这个参数中就可以指定实现了回调接口的对象,从而响应回调通知。运行客户端多个实例,发送消息,每个消息都会通知到所有客户端,与我们预期结果一致。

WCF入门(六)——回调相关推荐

  1. Docker入门六部曲——Swarm

    原文链接:http://www.dubby.cn/detail.html?id=8738 准备工作 安装Docker(版本最低1.13). 安装好Docker Compose,上一篇文章介绍过的. 安 ...

  2. Docker入门六部曲——Stack

    原文链接:http://www.dubby.cn/detail.html?id=8739 准备知识 安装Docker(版本最低1.13). 阅读完Docker入门六部曲--Swarm,并且完成其中介绍 ...

  3. Docker入门六部曲——服务

    原文链接:http://www.dubby.cn/detail.html?id=8735 准备 已经安装好Docker 1.13或者以上的版本. 安装好Docker Compose.如果你是用的是Do ...

  4. [WCF编程]1.WCF入门示例

    一.WCF是什么? Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,整合了原有的windows通讯的 .net Remotin ...

  5. WCF 入门之旅(4): 怎样用客户端调用WCF服务

    WCF 入门之旅(4): 怎样用客户端调用WCF服务 前面的demo已经能够跑起来,现在开始考虑用客户端来测试所写的应用了,首先用个普通的应用程序来调用所写的wcf服务吧.其实最后运行wcf服务后的页 ...

  6. Jmeter Web 性能测试入门 (六):Jmeter 解析 response 并传递 value

    解析response中的内容,并把获取到的value传递到后续的request中,常用的方法就是在想要解析response的request上添加后置处理器 本章介绍两种常用的组件 BeanShell ...

  7. WCF入门的了解准备工作

    了解WCF, 及WCF入门需要掌握哪里基本概念? 1.准备工作 >1.1 . XML >1.2 . Web Service >1.3 . 远程处理 (RPC) >1.4.  消 ...

  8. MySQL入门 (六) : 字元集与资料库

    1 Character Set与Collation 任何资讯技术在处理资料的时候,如果只是单纯的数值和运算,那就不会有太复杂的问题:如果处理的资料是文字的话,就会面临世界上各种不同语言的问题. 以资料 ...

  9. Python爬虫入门六之Cookie的使用

    大家好哈,上一节我们研究了一下爬虫的异常处理问题,那么接下来我们一起来看一下Cookie的使用. 为什么要使用Cookie呢? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在 ...

  10. 图论入门六:哥尼斯堡七桥问题

    转载自https://blog.csdn.net/saltriver/article/details/54585595 哥尼斯堡七桥问题: 1736年,年仅29岁的数学家欧拉来到普鲁士的古城哥尼斯堡( ...

最新文章

  1. 无需用户输入!Adobe提出自动生成高质量合成图像新方法
  2. 回顾丨2017年人工智能带火了哪些词
  3. Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析(上)...
  4. java多线程 -- 创建线程的第三者方式 实现Callable接口
  5. 【超全解析】原码、反码、补码、移码的相互转化和解读(取值范围)
  6. C语言里最基础的关键字
  7. python开发自己的工具包_爬虫开发python工具包介绍 (4)
  8. zbrush常用笔刷_如何制作精细模型,ZBrush中常用笔刷介绍
  9. linux下使用yum安装Apache+php+Mysql+phpMyAdmin
  10. LeetCode-3. 无重复字符的最长子串
  11. bzoj1596[Usaco2008 Jan]电话网络*
  12. java 管道流_Java IO7:管道流、对象流
  13. Spring启动NoClassDefFoundError中EmbeddedValueResolver错误
  14. spine骨骼动画基础一文通
  15. 直播平台常见直播礼物介绍
  16. 批量下载中国气象科学数据共享网的数据
  17. 一个人成熟的5大标志
  18. 计算机思维--0和1与逻辑
  19. 香橙派装php_【香橙派】安装宝塔面板 orange pi
  20. qt 绘制五角星图形

热门文章

  1. AIX系统文件安全性方面的几点考虑
  2. PaperWeekly 第二十三期 --- 机器写诗
  3. 从javascript发展说到vue
  4. 开源wkhtmltopdf使用心得 (一)
  5. Kali Linux 初上手记录 初始版本1.0.9
  6. Openssl rand命令
  7. 在Makefile中的 .PHONY 是做什么的?
  8. 转:MySQL性能优化神器Explain使用分析
  9. Failed to load or instantiate TagLibraryValidator class: org.apache.taglibs.
  10. 团队项目-北航MOOC系统Android客户端 NABC