zoukankan      html  css  js  c++  java
  • WCF系列之WCF的通信模式

    一、概述

    WCF在通信过程中有三种模式:请求与答复、单向、双工通信。以下我们一一介绍。

    二、请求与答复模式

    描述:

    客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务端有了答复后才能继续执行其他程序,如下图所示(图中的粗红线在此时代表顺序并不代表调用):

    请求与答复模式为WCF的默认模式,如下代码所示:

    [OperationContract]
     string ShowName(string name);

    即使返回值是void 也属于请求与答复模式。

    缺点:如果用WCF在程序A中上传一个2G的文件,那么要想执行程序B也许就是几个小时后的事情了。如果操作需要很长的时间,那么客户端程序的响应能力将会大大的下降。

    优点:有返回值我们就可以向客户端返回错误信息,如:只接收".rar"文件等信息。

    实例:

    //服务端接口
    using System.ServiceModel;
    
    namespace WCFService_Default
    {
        [ServiceContract]
        public interface IUser
        {
            [OperationContract]
            string ShowName(string name);
        }
    }
    //服务端实现
    namespace WCFService_Default
    {
        public class User : IUser
        {
            public string ShowName(string name)
            {
                //线程睡眠20秒钟
                System.Threading.Thread.Sleep(20000);
                return "WCF服务,显示名称:" + name;
            }
        }
    }
    
    //客户端调用
    using System;
    using WCFClient_Default.WCFService_Default;
    
    namespace WCFClient_Default
    {
        class Program
        {
            static void Main(string[] args)
            {
                UserClient client = new UserClient();
                Console.WriteLine(DateTime.Now);
                string result = client.ShowName("李林峰");
                Console.WriteLine(result);
                Console.WriteLine(DateTime.Now);
                Console.ReadLine();
            }
        }
    }

    在上例中,我们在服务端让线程睡眠20秒然后再返回客户端,那么客户端两次显示当前时间的间隔必然在20秒以上,如下图所示:

    二、单向模式

    描述:

    客户端向服务端发送求,但是不管服务端是否执行完成就接着执行下面的程序。如下图所示:

    单向模式要在OpertaionContract的属性中显示设置值,代码如下:

    [OperationContract(IsOneWay = true)]
    void ShowName(string name);

    优缺点与“请求响应模式”差不多倒过来。

    特点:使用 IsOneWay=true 标记的操作不得声明输出参数、引用参数或返回值

    实例:

    //服务端接口
    using System.ServiceModel;
    
    namespace WCFService_OneWay
    {
        [ServiceContract]
        public interface IUser
        {
            [OperationContract(IsOneWay = true)]
            void DoSomething();
        }
    }
    
    //服务端实现
    namespace WCFService_OneWay
    {
        public class User : IUser
        {
            public void DoSomething()
            {
                //线程睡眠20秒钟
                System.Threading.Thread.Sleep(20000);
            }
        }
    }
    
    //客户端调用
    using System;
    using WCFClient_OneWay.WCFService_OneWay;
    
    namespace WCFClient_OneWay
    {
        class Program
        {
            static void Main(string[] args)
            {
                UserClient client = new UserClient();
                Console.WriteLine(DateTime.Now);
                //调用WCF服务的方法
                client.DoSomething();
                Console.WriteLine(DateTime.Now);
                Console.ReadLine();
            }
        }
    }

    在单向模式中与请求响应模式最主要的就是加IsOneWay属性,运行效果如下:

    三、双工模式

    描述:

    双工模式建立在上面两种模式的基础之上,实现客户端与服务端相互的调用。相互调用:以往我们只是在客户端调用服务端,然后服务端有返回值返回客户端,而相互调用不光是客户端调用服务端,而且服务端也可以调用客户端的方法。如下图所示:

    在上图中,客户端的程序A调用服务端的程序A,服务程序A执行完成前又调用客户端的程序D,然后再返回到程序A,图有点乱,其实就是为了说明“服务端”与“客户端”可以相互调用,下面直接看代码。

    如我们所说的,双工模式是建立在以上两种模式之上的模式,他们并不冲突,代码如下:

    [ServiceContract(CallbackContract = typeof(IUserCallback))]
        public interface IUser
        {
            [OperationContract]
            string ShowName(string name);
        }
       //回调的接口 
        public interface IUserCallback
        {
            [OperationContract(IsOneWay = true)]
            void PrintSomething(string str);
        }

    实例:

    支持回调的绑定有4种:WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding、NetPeerTcpBinding。我们这里用WSDualHttpBinding为例

    //配置文件中的 binding 指定
    <endpoint address=""  binding="wsDualHttpBinding" contract="WCFService_DualPlex.IUser"></endpoint>
    
    //服务端接口
    using System.ServiceModel;
    
    namespace WCFService_DualPlex
    {
        [ServiceContract(CallbackContract = typeof(IUserCallback))]
        public interface IUser
        {
            [OperationContract]
            string ShowName(string name);
        }
    
        public interface IUserCallback
        {
            [OperationContract(IsOneWay = true)]
            void PrintSomething(string str);
        }
    }
    
    //服务端实现
    using System.ServiceModel;
    
    namespace WCFService_DualPlex
    {
        public class User : IUser
        {
            IUserCallback callback = null;
    
            public User()
            {
                callback = OperationContext.Current.GetCallbackChannel<IUserCallback>();
            }
    
            public string ShowName(string name)
            {
                //在服务器端定义字符串,调用客户端的方法向客户端打印
                string str = "服务器调用客户端...";
                callback.PrintSomething(str);
                //返回服务端方法
                return "WCF服务,显示名称:" + name;
            }
        }
    }
    
    //客户端调用
    using System;
    using System.ServiceModel;
    using WCFClient_DualPlex.WCFService_DualPlex;
    
    namespace WCFClient_DualPlex
    {
        //实现服务端的回调接口
        public class CallbackHandler : IUserCallback
        {
            public void PrintSomething(string str)
            {
                Console.WriteLine(str);
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                InstanceContext instanceContext = new InstanceContext(new CallbackHandler());
                UserClient client = new UserClient(instanceContext);
                Console.WriteLine(DateTime.Now);
                string result = client.ShowName("李林峰");
                Console.WriteLine(result);
                Console.WriteLine(DateTime.Now);
                Console.ReadLine();
            }
        }
    }

    在上例中,我们把接口定义在服务端,而实现在客户端,配置文件是由IDE自动生成的,我们在服务端ShowName方法中,调用了PringSomething的方法,实现了服务端向客户端的调用。

    执行效果如下图所示:

    四、代码下载:

    10 WCF 教程

    五、版权

    转载请注明出处:http://www.cnblogs.com/iamlilinfeng

  • 相关阅读:
    神器Tampermonkey的安装使用
    记一些不错的知识博客
    redis入门到精通系列(九):redis哨兵模式详解
    redis入门到精通系列(八):redis的高可用--主从复制详解
    redis入门到精通系列(七):redis高级数据类型详解(BitMaps,HyperLogLog,GEO)
    redis入门到精通系列(六):redis的事务详解
    redis入门到精通系列(五):redis的持久化操作(RDB、AOF)
    redis入门到精通系列(四):Jedis--使用java操作redis详解
    jsp乱码
    Tomcat 9遇到错误开着怎么关闭
  • 原文地址:https://www.cnblogs.com/cmhunter/p/4245449.html
Copyright © 2011-2022 走看看