ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WCF-双工通讯

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

返回列表