WCF 双工通讯

双工通讯是指通讯双方可以同时互发消息

image

主要方法

  • OperationContext context=OperationContext.Current; //获取当前服务方法上下文
  • callback=context.GetCallbackChannel<ICallback>(); //获取回调契约(接口)实例对象,该对象由客户端通过通道传递过来
  • InstanceContext instance=new InstanceContext(new ImpCallback()) //创建一个InstanceContext实例对象,该对象传入一个实现了回调契约(接口)的实例
  • DuplexClient client=new DuplexClient(instance);//实例化客户端对象,传入回调契约实现,该方法由多个重载方法,如果配置中定义多个协议,需要指定是用哪个协议
  • 如: client = new StudentDuplexClient(context, "NetTcpBinding_IStudentDuplex");

下面以简单示例演示:

  1. 服务端

  • 服务端契约
using System.ServiceModel;
namespace WpfApp14.Services
{
    [ServiceContract(Namespace ="WcfExamples",
        SessionMode =SessionMode.Required,  //回话模式为请求模式
        CallbackContract =typeof(IStudentDuplexCallback))]   //回调契约
    public interface IStudentDuplex  
    {
        [OperationContract(IsOneWay = true)]
        void Login(string greeting);
    }
}

  • 回调契约
using System.ServiceModel;
namespace WpfApp14.Services
{
    public interface IStudentDuplexCallback
    {
        [OperationContract(IsOneWay = true)]
        void Receive(string response);
    }
}

  • 服务端契约实现
using System.ServiceModel;
using WpfApp14.Models;
namespace WpfApp14.Services
{
    public class StudentsDuplex : Student, IStudentDuplex
    {
        private IStudentDuplexCallback callback;
        public StudentsDuplex()
        {
            OperationContext context = OperationContext.Current;
            callback = context.GetCallbackChannel<IStudentDuplexCallback>();  //获取客户端回调对象
        }
        public void Login(string greeting)
        {
            callback.Receive("Hello"+greeting);  //通过回调接口对象(由客户端实现)回调客户端方法
            System.Threading.Thread.Sleep(1000);
            callback.Receive("你好,我是服务端");
        }
    }
}

  • 自定义服务宿主,启动WCF服务

  private void MainWindow_Loaded(object sender, RoutedEventArgs e)
  {
            ServiceHost host = new ServiceHost(typeof(StudentsDuplex));
                try
                {
                    host.Open();
                    foreach (var v in host.Description.Endpoints) {
                        txt.Text += v.ListenUri + "\n";
                    }
                    this.Title = this.Title+"  WCF服务开始监听";
                }
                catch (Exception ex)
                {
                    txt.Text = ex.Message;
                }
            
 }
  • 配置文件
<?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="WSDualHttpBinding_IStudentDuplex" />
      </wsDualHttpBinding>
    </bindings>
    <services>
      <service name="WpfApp14.Services.StudentsDuplex">
        <endpoint address="" binding="wsDualHttpBinding" contract="WpfApp14.Services.IStudentDuplex" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:10020/StudentsDuplex"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
  • 客户端

using System;
using System.ServiceModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using WpfApp14.ServiceReference3;  //引用服务端命名空间
namespace WpfApp14.Examples
{
    /// <summary>
    /// Page3.xaml 的交互逻辑
    /// </summary>
    public partial class Page3 : Page,IStudentDuplexCallback
    {
        private StudentDuplexClient client;  // 定义客户端引用
        public Page3()
        {
            InitializeComponent();
        }

        public void Receive(string response)
        {
            textBlock1.Text+="\n收到服务端发来的信息:"+response;
        }

        private async void Btn1_Click(object sender, RoutedEventArgs e)
        {
            InstanceContext context = new InstanceContext(this);
            client = new StudentDuplexClient(context);
            textBlock1.Text += "\n等待接收";
            Task login = client.LoginAsync("张三");
            while (login.IsCompleted == false) {
                textBlock1.Text += ".";
                await Task.Delay(TimeSpan.FromMilliseconds(500));

            }
            await login;
        }
    }
}

  • 客户端配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:10020/StudentsDuplex" binding="wsDualHttpBinding"
        bindingConfiguration="WSDualHttpBinding_IStudentDuplex" contract="ServiceReference3.IStudentDuplex"
        name="WSDualHttpBinding_IStudentDuplex">
        <identity>
          <userPrincipalName value="ZJZL-20240528TP\Administrator" />
        </identity>
      </endpoint>
	   <endpoint address="net.tcp://localhost:10021/StudentsDuplex"
        binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IStudentDuplex"
        contract="ServiceReference3.IStudentDuplex" name="NetTcpBinding_IStudentDuplex">
        <identity>
          <userPrincipalName value="ZJZL-20240528TP\Administrator" />
        </identity>
      </endpoint>
    </client>
    <bindings>
      <wsDualHttpBinding>
        <binding name="WSDualHttpBinding_IStudentDuplex" />
      </wsDualHttpBinding>
    </bindings>
  </system.serviceModel>
</configuration>
posted @ 2024-06-25 16:00  丹心石  阅读(24)  评论(0编辑  收藏  举报