当前位置: 首页 > news >正文

WCF-双工通讯

WCF双工通讯只要是通过调用由客户端实现的接口ICallback, 来实现服务端调用该接口方法来实现回调,从而把相关数据或对象传递到客户端的一种实现方式。当然目前通过WebSocket 也可以很容易实现,这里暂不讨论其他方法,只对WCF方法做一个简单的记录,以备忘记。


  • 服务端

服务端接口(契约)

using System.ServiceModel;[ServiceContract(CallbackContract =typeof(IClientCallback))]public interface IMyService{[OperationContract(IsOneWay = true)]void RegisterClient();[OperationContract]void SendMessage(string message);}

回调接口(该接口在服务端不实现,由客户端实现)

 [ServiceContract]public interface IClientCallback{[OperationContract(IsOneWay = true)]void NotifyClient(string message);[OperationContract(IsOneWay = true)]void ServerTimeUpdate(DateTime time);}

服务端实现接口类(即提供相关服务)

  //服务实现[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]public class MyService : IMyService{private IClientCallback callback;private Timer timer;public MyService() { //获取客户端回调通道callback=OperationContext.Current.GetCallbackChannel<IClientCallback>();}public void RegisterClient(){Console.WriteLine("客户端已连接");//设置定时器,定期向客户端发送服务器时间timer = new Timer(1000);timer.Elapsed += (s, e) => {try{callback.ServerTimeUpdate(DateTime.Now);} catch(Exception ex) {Console.WriteLine(ex.ToString());}};timer.Start();}public void SendMessage(string message){Console.WriteLine($"收到客户端消息:{message}");//向客户端发送响应callback.ServerTimeUpdate(DateTime.Now);}}

服务端启动WCF方法

  internal class Program{static void Main(string[] args){using (ServiceHost host = new ServiceHost(typeof(MyService))){try {host.Open();Console.WriteLine("双工服务已启动!");foreach (var ep in host.Description.Endpoints){Console.WriteLine(ep.ListenUri);}}catch(Exception ex)  {Console.WriteLine(ex.Message);}Console.ReadKey();}}}

服务端配置文件

<system.serviceModel><services><service name="DuplexService.Services.MyService"><endpoint address="" binding="wsDualHttpBinding" contract="DuplexService.Services.IMyService" /><endpoint address="" binding ="netTcpBinding" contract="DuplexService.Services.IMyService" /><host><baseAddresses><add baseAddress="http://localhost:10020/MyService"/><add baseAddress="net.tcp://localhost:10021/MyService" /></baseAddresses></host></service></services><behaviors><serviceBehaviors><behavior><serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/></behavior></serviceBehaviors></behaviors>
</system.serviceModel>

客户端

客户端对回调接口的实现

 public class ClientCallback : IMyServiceCallback{/// <summary>/// 服务端通过回调接口来对客户端实例方法进行回调,给客户端传递消息/// </summary>/// <param name="message"></param>/// <exception cref="NotImplementedException"></exception>public void NotifyClient(string message){Console.WriteLine($"收到服务端发送的消息:{message}");}/// <summary>/// 服务端通过回调接口来对客户端实例方法进行回调,给客户端传递时间/// </summary>/// <param name="time"></param>/// <exception cref="NotImplementedException"></exception>public void ServerTimeUpdate(DateTime time){Console.WriteLine($"收到服务端回发的更新时间:{time.ToString("YYYY-MM-dd hh:mm:ss")}");}}

客户端实现双通道调用

 internal class Program{static void Main(string[] args){//创建回调实例和实例上下文ClientCallback callback= new ClientCallback();InstanceContext context = new InstanceContext(callback);//创建双通道工厂(提供创建和管理不同类型的双工通道的方式,客户端使用这些通道在服务终结点发送和接收消息)DuplexChannelFactory<IMyService> fact = new DuplexChannelFactory<IMyService>(context,new NetTcpBinding(),new EndpointAddress("net.tcp://localhost:10021/MyService"));//创建到指定终结点指定类型的通道IMyService channel = fact.CreateChannel();try {//注册客户端channel.RegisterClient();Console.WriteLine("已连接到服务器,输入消息发送给服务器");string input;while ((input = Console.ReadLine()) != "exit"){channel.SendMessage(input);}channel.SendMessage("客户端退出");}catch (Exception ex){Console.WriteLine($"发生错误:{ex.Message}");//使通讯对象从其当前状态转换到关闭状态channel.Stop();fact.Close();}}}

客户端配置文件

 <system.serviceModel><bindings><netTcpBinding><binding name="NetTcpBinding_IMyService"><security><transport sslProtocols="None" /></security></binding></netTcpBinding><wsDualHttpBinding><binding name="WSDualHttpBinding_IMyService" /></wsDualHttpBinding></bindings><client><endpoint address="http://localhost:10020/MyService" binding="wsDualHttpBinding"bindingConfiguration="WSDualHttpBinding_IMyService" contract="ServiceReference1.IMyService"name="WSDualHttpBinding_IMyService"><identity><userPrincipalName value="DESKTOP-H27UFUR\Administrator" /></identity></endpoint><endpoint address="net.tcp://localhost:10021/MyService" binding="netTcpBinding"bindingConfiguration="NetTcpBinding_IMyService" contract="ServiceReference1.IMyService"name="NetTcpBinding_IMyService"><identity><userPrincipalName value="DESKTOP-H27UFUR\Administrator" /></identity></endpoint></client></system.serviceModel>

效果

  • 服务端
    image

  • 客户端
    image

http://www.gsyq.cn/news/10080.html

相关文章:

  • 跨网文件安全交换系统:打破数据壁垒的高效之选!
  • 【F#学习】可区分联合 Discriminated Unions
  • 大环境不好,这几个赚钱网站可以试试
  • Model Context Protocol (MCP) 完整协议流程详解
  • C#和Lua相互访问 - 详解
  • jemter 安装
  • Day20创建对象内存分析
  • 熬夜三天!SpringCloud Gateway 动态路由失效,背后黑手竟是它……
  • cmd 执行git bash 命令
  • 基于Python+Vue开发的新闻管理系统源码+运行步骤
  • Spring框架中的注解主要有哪些
  • 探索 12 种 3D 文件格式:综合指南
  • 强化学习算法如何控制人形机器人行走的 —— 策略映射动作,动作如何控制电机?
  • list集合根据某字段获取某个对象
  • 后缀数组基础 Suffix Array
  • 完整教程:第33章 AI在教育领域的应用
  • 易软通openWMS - 功能齐全的开源WMS
  • 遇到一件循环导入事件
  • 上海这样的地段简直是逆天
  • 【GitHub每日速递 250923】 Google 又放大招!TimesFM 2.5 参数减半,预测更准更快
  • 具身智能机器人架构:人形机器人系统架构深度拆解
  • 卓驭,欧洲无绝境
  • 下周审核4家IPO,2家再融资。其中两家IPO企业于在审期间调减募资规模
  • Java 与大数据实时处理:Kafka、Flink 与企业应用
  • Java 与企业级中间件:消息、缓存与数据库集成
  • 测试测试测试测试测试
  • 一些正在制作的“格林达姆”测试项目,以及“假无损”
  • 九月22号
  • 25.9.22 继续MySQL
  • 开机RAM分析调试SOP