• WCF之双工服务


    所谓WCF的双工服务,指的就是说,在WCF应用中,可能客户端和服务器端的角色是可以互换的,例如服务器端一般可能仅仅提供操作服务,它并不需要主动地联系客户端做什么操作。

    但是,假如某些时候,我们需要服务端也能够具备这样的特征,就是说他能够在某些时候主动地联系客户端,触发一个行为。

    这种场景,我们简单地归纳为“双工”场景。下面来看看在WCF中如何实现这种双工的服务。

    1. 创建一个用于回调的Contract。它与标准的Contract没有任何区别

    using System;
    using System.Collections.Generic;
    using System.Text;

    using System.ServiceModel;

    namespace Contracts
    {
        /// <summary>
        /// 这是一个回调的合约,用于服务器端对客户端进行回复
        /// </summary>
        [ServiceContract]
        public interface ICallbackContract
        {
            [OperationContract]
            void ServerReply(string originalMessage);
        }
    }

     

    2. 在我们用于业务操作的Contract中,加入一个声明,就是指定回调的Contract类型是第一步创建的这个

    using System;
    using System.Collections.Generic;
    using System.Text;

    using System.ServiceModel;

    namespace Contracts
    {
        [ServiceContract(CallbackContract=typeof(ICallbackContract))]
        public interface IChatContract
        {
            [OperationContract]
            void SendMessage(string message);
        }
    }

    3. 在服务端的设计

    using System;
    using System.Collections.Generic;
    using System.Text;

    using System.ServiceModel;
    using Contracts;

    namespace Services
    {
       [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
        public class ChatService:IChatContract
        {
            #region IChatContract 成员

            public void SendMessage(string message)
            {
                Console.WriteLine(string.Format("{0} 收到客户端的消息:{1}", DateTime.Now.ToString(), message));

               ICallbackContract callback = OperationContext.Current.GetCallbackChannel<ICallbackContract>();

                callback.ServerReply("服务器处理了"+message);//大家注意到,这里,服务端可以根据情况发回一个回复的消息
            }

            #endregion
        }
    }

     

    4.客户端的设计

    编写一个实现了回调合约的Handler,实际上就是说,如果服务器回复了消息,那么客户端自己该怎么做

    class CallbackHandler : Contracts.ICallbackContract {

        #region ICallbackContract 成员

        public void ServerReply(string originalMessage)
        {
            Console.WriteLine("{0} 收到服务器回复:{1}", DateTime.Now, originalMessage);
        }

        #endregion
    }

     

    创建服务的本地代理的时候,需要定义一个比较特殊的构造函数

    class ChatServiceClient : ClientBase<Contracts.IChatContract>, Contracts.IChatContract {

        public ChatServiceClient(InstanceContext callback,Binding binding, EndpointAddress address) : base(callback,binding, address) { }

        #region IChatContract 成员

        public void SendMessage(string message)
        {
            Channel.SendMessage(message);
        }

        #endregion
    }

     

    客户端代码

    static void Main(string[] args)
    {
       Binding binding = new WSDualHttpBinding();//这里必须用WSDualHttpBinding
        EndpointAddress address = new EndpointAddress("http://localhost:9000/ChatService");
        CallbackHandler callback = new CallbackHandler();
        ChatServiceClient proxy = new ChatServiceClient(new InstanceContext(callback),binding, address);

        Console.Write("请输入:");
        string input = Console.ReadLine();

        while (input != "Exit")
        {
            proxy.SendMessage(input);
            Console.WriteLine();
            Console.Write("请输入:");
            input = Console.ReadLine();
        }

    }

     

     

    最后我们看到的就是一个简单的聊天程序

    初始化状态

    image image

    聊天中的状态

    image image

  • 相关阅读:
    广东省第三届普通高中信息技术优质课交流评选活动参后感
    预说课
    arraylist和list的区别
    List 泛型类 详解
    C#中const和readonly的区别
    PHP array_walk() 函数
    栈,堆,代码区,全局(静态)区 ,常量区
    PHP_SELF、 SCRIPT_NAME、 REQUEST_URI区别
    c#中Dictionary、ArrayList、Hashtable和数组的区别(
    PHP文件包含语句 include、include_once、require、require_once
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1489078.html
Copyright © 2020-2023  润新知