5 wcf双工

1 创建两个项目

Wcf_WsDual_Service   Wcf_WsDual_Client

2 Wcf_WsDual_Service   项目中创建 LoginService.cs 的wcf文件

using System.ServiceModel;

namespace Wcf_WsDual_Service
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“ILogin”。
    //注意此处构造函数里面的回调
    [ServiceContract(CallbackContract =typeof(ICallBack))]
    public interface ILoginService
    {
        [OperationContract]
        void Login(string username);
    }
    //注意此处添加了回调接口
    [ServiceContract]
    public interface ICallBack
    {
        [OperationContract]
        void Notify(string msg);
    }
}
ILoginService
using System;
using System.Collections.Generic;
using System.ServiceModel;

namespace Wcf_WsDual_Service
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Login”。
    public class LoginService : ILoginService
    {
        //存储所有请求了这个服务的客户端管道
        public static Dictionary<string, ICallBack> channelDic = new Dictionary<string, ICallBack>();
        void ILoginService.Login(string username)
        {
            //获得请求带ICallBack的endpoint的channel
            var callback = OperationContext.Current.GetCallbackChannel<ICallBack>();
            channelDic[username] = callback;
            Console.WriteLine($"用户{username}已经登录");
        }
        //服务端动作
        public static void OperateAction()
        {
            while (true)
            {
                string msg = Console.ReadLine();
                if (!string.IsNullOrEmpty(msg))
                {
                    //遍历客户端管道 向这些管道发送消息
                    foreach (var item in channelDic)
                    {
                        item.Value.Notify(msg);
                    }

                }

            }
        }
    }
}
LoginService

3 修改服务配置文件

   a 将协议改成双工  b将对应双工的安全设置成无安全      

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
    <system.serviceModel>

     <!--双工默认有安全验证 这里取消安全-->
      <bindings>
        <wsDualHttpBinding>
          <binding name="MyDual">
            <security mode="None"></security>
          </binding>
        </wsDualHttpBinding>
      </bindings>
      
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service name="Wcf_WsDual_Service.LoginService">
                <endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="MyDual"
                    contract="Wcf_WsDual_Service.ILoginService">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8988/Design_Time_Addresses/Wcf_WsDual_Service/Login/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
</configuration>
appConfig

 4.在服务端main方法中启动服务,并异步启动线程用以向客户端发送消息

using System;
using System.ServiceModel;
using System.Threading.Tasks;

namespace Wcf_WsDual_Service
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(LoginService));
            host.Open();
            Console.WriteLine("服务已经启动");
            Task.Run(() =>
            {
                LoginService.OperateAction();
            });

            System.Threading.Thread.Sleep(int.MaxValue);
        }
       
    }
    
}
Program

5.客户端引用服务引用

6.客户端创建一个LoginCallBack类实现服务端定义的iLoginCallBack接口

  public class LoginCallBack : ILoginServiceCallback
    {
        public void Notify(string msg)
        {
            Console.WriteLine(msg);
        }
    }
LoginCallBack

7.客户端main方法创建一个服务实例,并想服务发送请求,在服务端这个请求会记录下这个请求对应的客户端的信息

 class Program
    {
        static void Main(string[] args)
        {
            var instanceContext = new InstanceContext(new LoginCallBack());
            LoginServiceClient client = new LoginServiceClient(instanceContext);
            client.Login("winner");
            Console.ReadKey();
        }
    }
客户端Program

8.这样启动服务之后,再启动客户端,客户端会给服务端发送一个请求,服务端会记录下客户端的endpoint等信息创建一个针对客户端的管道,服务端就可以利用这个管道向服务端发送消息了

 

posted @ 2018-12-23 22:11  当年在远方  阅读(269)  评论(0编辑  收藏  举报