• 我所知道的CallbackContract in WCF


    参考网址:https://www.cnblogs.com/scy251147/archive/2012/11/26/2789432.html

    由于WCF中提供了CallbackContract属性,所以在双工通信中,我们可以很方便的和Server进行通信。虽然查遍了MSDN,也看过了它提供的例子,但是还是不知道怎么来使用(因为MSDN中只是给你提供了Server端的调用方法,并没有客户端的调用方式,所以例子没法儿跑起来,当然也就不能够从示例中看出CallbackContract属性的工作方式,鄙视下,呵呵)。在这篇文章中,我要做的就是让这个例子能够顺利地跑起来,从而了解CallbackContract的工作方式。

    服务端编写

    首先,创建一个名称为CallbackContractWCF的控制台项目,添加一个DuplexHello类作为我们的Service,具体代码就Copy了MSDN上面的:

    using System;
    using System.ServiceModel;
    using System.Threading;
    
    namespace CallbackContractWCF
    {
        [ServiceContract(Name = "SampleDuplexHello", CallbackContract = typeof(IHelloCallbackContract), SessionMode = SessionMode.Required)]
        public interface IDuplexHello
        {
            [OperationContract(IsOneWay = true)]
            void Hello(string greeting);
        }
    
        public interface IHelloCallbackContract
        {
            [OperationContract(IsOneWay = true)]
            void Reply(string responseToGreeting);
        }
    
        public class DuplexHello:IDuplexHello
        {
            public DuplexHello()
            {
                Console.WriteLine("Service object created: " + this.GetHashCode().ToString());
            }
    
            ~DuplexHello()
            {
                Console.WriteLine("Service object distroyed: " + this.GetHashCode().ToString());
            }
    
            public void Hello(string greeting)
            {
                Console.WriteLine("Caller sent: "+greeting);
                Console.WriteLine("Session ID: "+OperationContext.Current.SessionId);
                Console.WriteLine("Waiting two seconds before returning call.");
                Thread.Sleep(2000);
                IHelloCallbackContract callerProxy = OperationContext.Current.GetCallbackChannel<IHelloCallbackContract>();
                string response = "Service object " + this.GetHashCode().ToString() + " received." + greeting;
                Console.WriteLine("Sending back: " + response);
                callerProxy.Reply(response);
            }
        }
    }
    复制代码
    using System;
    using System.ServiceModel;
    using System.Threading;
    
    namespace CallbackContractWCF
    {
        [ServiceContract(Name = "SampleDuplexHello", CallbackContract = typeof(IHelloCallbackContract), SessionMode = SessionMode.Required)]
        public interface IDuplexHello
        {
            [OperationContract(IsOneWay = true)]
            void Hello(string greeting);
        }
    
        public interface IHelloCallbackContract
        {
            [OperationContract(IsOneWay = true)]
            void Reply(string responseToGreeting);
        }
    
        public class DuplexHello:IDuplexHello
        {
            public DuplexHello()
            {
                Console.WriteLine("Service object created: " + this.GetHashCode().ToString());
            }
    
            ~DuplexHello()
            {
                Console.WriteLine("Service object distroyed: " + this.GetHashCode().ToString());
            }
    
            public void Hello(string greeting)
            {
                Console.WriteLine("Caller sent: "+greeting);
                Console.WriteLine("Session ID: "+OperationContext.Current.SessionId);
                Console.WriteLine("Waiting two seconds before returning call.");
                Thread.Sleep(2000);
                IHelloCallbackContract callerProxy = OperationContext.Current.GetCallbackChannel<IHelloCallbackContract>();
                string response = "Service object " + this.GetHashCode().ToString() + " received." + greeting;
                Console.WriteLine("Sending back: " + response);
                callerProxy.Reply(response);
            }
        }
    }
    复制代码

    从这个类中,我们可以看到它有一个IHelloCallbackContract的接口,由于它在ServiceContract中被标记为CallbackContract = typeof(IHelloCallbackContract),所以它用于客户端回调。意即,服务端可以通过此接口中的方法将数据发送给客户端,客户端只需要实现此接口,即可接收到服务端发送过来的消息。

    然后是创建配置文件,请参见我的文章:基于net.tcp的WCF配置实例解析。这里我们使用的EndPoint为:net.tcp://127.0.0.1/DuplexHello,创建好App.config配置文件后,拷贝到CallbackContractWCF项目下,然后打开Program.cs文件,编码以便让服务端能够启动监听:

    using (ServiceHost host = new ServiceHost(typeof(DuplexHello)))
                {
                    ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        host.Description.Behaviors.Add(new ServiceMetadataBehavior());
                    }
    //暴露MetaData,以便能够让SvcUtil.exe工具生成客户端代理类和配置文件
                    host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
                    host.Open();
                    Console.WriteLine("service listen on endpoint ...");
                    Console.WriteLine("Press ENTER to stop ...");
                    Console.ReadLine();
                    host.Abort();
                    host.Close();
                }
    复制代码
    using (ServiceHost host = new ServiceHost(typeof(DuplexHello)))
                {
                    ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        host.Description.Behaviors.Add(new ServiceMetadataBehavior());
                    }
    //暴露MetaData,以便能够让SvcUtil.exe工具生成客户端代理类和配置文件
                    host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
                    host.Open();
                    Console.WriteLine("service listen on endpoint ...");
                    Console.WriteLine("Press ENTER to stop ...");
                    Console.ReadLine();
                    host.Abort();
                    host.Close();
                }
    复制代码

    好了,启动服务端,我们可以看到如下界面,服务端启动成功了:

    客户端编写 

    下面开始来编写客户端。

    首先打开SvcUtil.exe,按照文章:基于net.tcp的WCF配置实例解析 中介绍的方法,生成output.config文件和DuplexHello.cs代理类文件。

    其次创建一个名称为CallbackContractWCFClient的Windows Form Application项目,将上面的两个文件拷贝进来,并修改output.config名称为App.config。

    然后打开ClientForm窗体,继承自SampleDuplexHelloCallback接口(这个接口也就是服务端的IHelloCallbackContract接口的代理),然后编写以下代码进行数据发送和接收:

    using System;
    using System.Windows.Forms;
    using System.ServiceModel;
    
    namespace CallbackContractWCFClient
    {
        public partial class ClientForm : Form, SampleDuplexHelloCallback
        {
            public ClientForm()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                InstanceContext site = new InstanceContext(this);
                SampleDuplexHelloClient client = new SampleDuplexHelloClient(site);
    
                string msg =" This is a Client Message sent to Server side...";
                label1.Text = "Client Sent: " + msg;
                client.Hello(msg);
               
            }
    
            public void Reply(string responseToGreeting)
            {
                label2.Text = "Server Reply: " + responseToGreeting;
            }
    
        }
    }
    复制代码
    using System;
    using System.Windows.Forms;
    using System.ServiceModel;
    
    namespace CallbackContractWCFClient
    {
        public partial class ClientForm : Form, SampleDuplexHelloCallback
        {
            public ClientForm()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                InstanceContext site = new InstanceContext(this);
                SampleDuplexHelloClient client = new SampleDuplexHelloClient(site);
    
                string msg =" This is a Client Message sent to Server side...";
                label1.Text = "Client Sent: " + msg;
                client.Hello(msg);
               
            }
    
            public void Reply(string responseToGreeting)
            {
                label2.Text = "Server Reply: " + responseToGreeting;
            }
    
        }
    }
    复制代码

    这样,我们的服务端和客户端就写好了,接下来运行,结果显示如下:

    服务端:

     客户端:

    源码下载

    点击这里下载

     
     
  • 相关阅读:
    ABP无法使用异步操作,但要调用异步方法
    ABP 领域服务层学习记录
    Postman 简单使用随笔记
    Abp 模板更换数据库 版本为V5.x,遇到的问题
    C# 求两个时间的差值
    Mysql 为现有数据生成Guid
    设计模式之单例模式
    iOS基础(十八)——调整图片尺寸和大小
    iOS基础(十七)——根据一个View生成一个image
    iOS基础(十六)——动态获取label的高度
  • 原文地址:https://www.cnblogs.com/bruce1992/p/15425843.html
Copyright © 2020-2023  润新知