当前位置: 首页 > 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.hskmm.com/?act=detail&tid=14423

相关文章:

  • 跨网文件安全交换系统:打破数据壁垒的高效之选!
  • 【F#学习】可区分联合 Discriminated Unions
  • Midscene.js - 开源的 AI 操作助手 - 广东靓仔
  • 详细介绍:【Datawhale25年9月组队学习:llm-preview+Task1:大模型介绍与环境配置】
  • Git仓库ssh不同环境配置
  • 超大附件怎么发送的高效解决方案与技巧
  • dm sql 缓存区
  • 给国外传输大文件的最佳策略与解决方案
  • idea mvn package 报错java head space/ java.lang.OutOfMemoryError: Java heap space
  • 大环境不好,这几个赚钱网站可以试试
  • Day20类与对象的小结
  • 电流探头的测试原理
  • 第四届云计算、大数据应用与软件工程国际学术会议(CBASE 2025)
  • Neo4j常用的语句记录
  • p1-1002
  • Model Context Protocol (MCP) 完整协议流程详解
  • 常用的 HTTP 请求方法和区别
  • 第七届机器学习、大数据与商务智能国际会议(MLBDBI 2025)
  • 【OpenCV】11 形态学操作
  • 安装与使用trex
  • 自建 Supabase 云服务与 BeeCount 云同步详解
  • CF2134 Codeforces Round 1045 (Div. 2) 游记(VP)
  • jemter 安装
  • Day20创建对象内存分析
  • 熬夜三天!SpringCloud Gateway 动态路由失效,背后黑手竟是它……
  • cmd 执行git bash 命令
  • 安全向量模板类SiVector - 实践
  • 最佳三维文件格式,以及怎么在线浏览编辑FBX/OBJ/GLB/GLTF
  • FR报表下拉框高度(JS添加css样式方式)调整
  • 基于Python+Vue开发的新闻管理系统源码+运行步骤