实现双工通讯主要分三步。

  1. 通信接口的定义;
  2. 被调用接口的实现
  3. 双工通道的建立

请先引用DLL(CSDN的代码编辑器真尼玛蛋疼)

整个解决方案的结构

1、通信接口的定义;

服务端调用客户端接口IServerCallClient

  1. /// <summary>
  2. /// 服务器调用客户端接口
  3. /// </summary>
  4. public interface IServerCallClient
  5. {
  6. /// <summary>
  7. /// 服务器读取客户端的IP
  8. /// </summary>
  9. /// <returns></returns>
  10. [OperationContract]
  11. IPEndPoint ServerRequestCLientIP();
  12. /// <summary>
  13. /// 服务器发送消息给客户端
  14. /// </summary>
  15. /// <param name="text"></param>
  16. [OperationContract]
  17. void ServerSayMSG(string text);
  18. }
    /// <summary>
/// 服务器调用客户端接口
/// </summary>
public interface IServerCallClient
{
/// <summary>
/// 服务器读取客户端的IP
/// </summary>
/// <returns></returns>
[OperationContract]
IPEndPoint ServerRequestCLientIP();
/// <summary>
/// 服务器发送消息给客户端
/// </summary>
/// <param name="text"></param>
[OperationContract]
void ServerSayMSG(string text);
}

客户端调用服务端接口IClientCallServer

  1. <span style="font-weight: normal;">    [ServiceContract(CallbackContract =typeof(IServerCallClient))]//指定回调的接口
  2. public interface IClientCallServer
  3. {
  4. /// <summary>
  5. /// 客户端发送消息给服务器
  6. /// </summary>
  7. /// <param name="text"></param>
  8. [OperationContract]//指定操作约束,不添加该接口方法不可使用
  9. void ClientSayToServer(string text);
  10. /// <summary>
  11. /// 客户端读取服务端时间
  12. /// </summary>
  13. /// <returns></returns>
  14. [OperationContract]
  15. DateTime ClientRequestTime();
  16. }</span>
<span style="font-weight: normal;">    [ServiceContract(CallbackContract =typeof(IServerCallClient))]//指定回调的接口
public interface IClientCallServer
{
/// <summary>
/// 客户端发送消息给服务器
/// </summary>
/// <param name="text"></param>
[OperationContract]//指定操作约束,不添加该接口方法不可使用
void ClientSayToServer(string text);
/// <summary>
/// 客户端读取服务端时间
/// </summary>
/// <returns></returns>
[OperationContract]
DateTime ClientRequestTime();
}</span>

上面的两个接口是单独的一个项目。

双方谈好了就好互相实现对方的方法。

2、被调用接口的实现

客户端实现服务端接口的类:

  1. class ServerCallClient :IServerCallClient
  2. {
  3. public IPEndPoint ServerRequestCLientIP()
  4. {
  5. var ip =new IPEndPoint(IPAddress.Any,10086);
  6. return ip;
  7. }
  8. public void ServerSayMSG(string text)
  9. {
  10. File.AppendAllText("收到的数据", text);
  11. }
  12. }
    class ServerCallClient :IServerCallClient
{
public IPEndPoint ServerRequestCLientIP()
{
var ip =new IPEndPoint(IPAddress.Any,10086);
return ip;
}
public void ServerSayMSG(string text)
{
File.AppendAllText("收到的数据", text);
}
}

服务端实现客户端接口的类

  1. /// <summary>
  2. /// 客户回调服务器类
  3. /// </summary>
  4. [ServiceBehavior(InstanceContextMode =InstanceContextMode.Single)]//通道只建立一个除非断开才新建(SessionID是同一个)
  5. public class ClientCallServer : IClientCallServer, IDisposable
  6. {
  7. public static List<IServerCallClient> ServerCallClientList { get; set; }=new List<IServerCallClient>();
  8. /// <summary>
  9. /// 返回服务器时间
  10. /// </summary>
  11. /// <returns></returns>
  12. public DateTime ClientRequestTime()
  13. {
  14. return DateTime.Now;
  15. }
  16. /// <summary>
  17. /// 客户端列表
  18. /// </summary>
  19. /// <summary>
  20. /// 服务端向客户端发数据
  21. /// </summary>
  22. /// <param name="text"></param>
  23. public void ClientSayToServer(string text)
  24. {
  25. var info = OperationContext.Current;
  26. File.AppendAllText("receive.txt",info.SessionId+text);//收到的数据存在文件
  27. }
  28. public void Dispose()
  29. {
  30. ServerCallClientList.Clear();
  31. }
  32. #endregion
  33. }
    /// <summary>
/// 客户回调服务器类
/// </summary>
[ServiceBehavior(InstanceContextMode =InstanceContextMode.Single)]//通道只建立一个除非断开才新建(SessionID是同一个)
public class ClientCallServer : IClientCallServer, IDisposable
{
public static List<IServerCallClient> ServerCallClientList { get; set; }=new List<IServerCallClient>();
/// <summary>
/// 返回服务器时间
/// </summary>
/// <returns></returns>
public DateTime ClientRequestTime()
{
return DateTime.Now;
}
/// <summary>
/// 客户端列表
/// </summary>
/// <summary>
/// 服务端向客户端发数据
/// </summary>
/// <param name="text"></param>
public void ClientSayToServer(string text)
{
var info = OperationContext.Current;
File.AppendAllText("receive.txt",info.SessionId+text);//收到的数据存在文件
}
public void Dispose()
{
ServerCallClientList.Clear();
}
#endregion
}

3、双工通道的建立

服务端通道的建立

  1. ServiceHost serviceHost = new ServiceHost(typeof(ClientCallServer));//<span style="font-family: Arial, Helvetica, sans-serif;">指定回调的类</span>
  2. serviceHost.AddServiceEndpoint(typeof(IClientCallServer),new WSDualHttpBinding(), "http://localhost:12345");//指定客户端的接口,通讯格式,服务器的地址
  3. serviceHost.BeginOpen(callback=>
  4. {
  5. serviceHost.EndOpen(callback);
  6. textBox1.Invoke(new Action(delegate {//不解释也能看得懂吧
  7. textBox1.AppendText("服务开启" + Environment.NewLine);
  8. }));
  9. },null);
            ServiceHost serviceHost = new ServiceHost(typeof(ClientCallServer));//<span style="font-family: Arial, Helvetica, sans-serif;">指定回调的类</span>
serviceHost.AddServiceEndpoint(typeof(IClientCallServer),new WSDualHttpBinding(), "http://localhost:12345");//指定客户端的接口,通讯格式,服务器的地址
serviceHost.BeginOpen(callback=>
{
serviceHost.EndOpen(callback);
textBox1.Invoke(new Action(delegate {//不解释也能看得懂吧
textBox1.AppendText("服务开启" + Environment.NewLine);
}));
},null);

客户端通道的建立

  1. var rand = new Random();
  2. InstanceContext context = new InstanceContext(new ServerCallClient());//指定回调的类
  3. WSDualHttpBinding binding = new WSDualHttpBinding() { ClientBaseAddress = new Uri($"http://localhost:{rand.Next(10000, 20000)}") };//指定客户端地址;
  4. using (DuplexChannelFactory proxy = new DuplexChannelFactory(context, binding))//创建通道管理器
  5. {
  6. IClientCallServer client = proxy.CreateChannel(new EndpointAddress("http://localhost:12345"));// 创建用于将消息发送到特定终结点地址的服务的通道client.ClientRequestTime();
  7. client.ClientSayToServer("尼玛");
  8. }

Winfrom 使用WCF 实现双工通讯的更多相关文章

  1. 利用WCF的双工通讯实现一个简单的心跳监控系统

    何为心跳监控系统? 故名思义,就是监控某个或某些个程序的运行状态,就好比医院里面的心跳监视仪一样,能够随时显示病人的心跳情况. 心跳监控的目的是什么? 与医院里面的心跳监视仪目的类似,监控程序运行状态 ...

  2. 利用WCF的双工通讯实现一个简单的心跳监控系统 z

    利用WCF的双工通讯实现一个简单的心跳监控系统 http://www.cnblogs.com/zuowj/p/5761011.html 何为心跳监控系统? 故名思义,就是监控某个或某些个程序的运行状态 ...

  3. WCF双工通讯以及客户端间的间接通讯

    由于学习计划安排不当,对WCF的认知一直停滞不前,最近工作上又用回了WCF,重拾一下,看到蒋老师介绍双工通讯的博文,实践一下,积累一下.原想着WCF的双工通讯就是原本的客户端能调用服务端的方法之余,服 ...

  4. WCF初探-5:WCF消息交换模式之双工通讯(Duplex)

    双工通讯Duplex具有以下特点: 1它可以在处理完请求之后,通过请求客户端中的回调进行响应操作 2.消息交换过程中,服务端和客户端角色会发生调换 3.服务端处理完请求后,返回给客户端的不是reply ...

  5. WCF消息交换模式之双工通讯(Duplex)

    WCF消息交换模式之双工通讯(Duplex) 双工通讯Duplex具有以下特点: 1它可以在处理完请求之后,通过请求客户端中的回调进行响应操作 2.消息交换过程中,服务端和客户端角色会发生调换 3.服 ...

  6. 浅谈WCF的三种通信模式:请求响应模式、数据报模式和双工通讯模式

    一: WCF的服务端与客户端在通信时有三种模式:请求响应模式.数据报模式和双工通讯模式. 说一下基本知识,  1.如果想要将当前接口作为wcf服务器,则一定要加上[ServiceContract] 契 ...

  7. 一: WCF的服务端与客户端在通信时有三种模式:请求响应模式、数据报模式和双工通讯模式。

    说一下基本知识,  1.如果想要将当前接口作为wcf服务器,则一定要加上[ServiceContract] 契约 2.要想将方法作为wcf服务方法发布给外部调用,则一定要加上    [Operatio ...

  8. wcf双工通讯

    首先说一个服务引用不成功的解决办法: 需要把服务端配置文件中的Binding换成: <endpoint address="" binding="BasicHttpB ...

  9. wcf双工通讯遇到的问题

    1.向ChannelFactory提供的InstanceContext包含未实现CallbackContractType的问题 通过添加服务引用生成的客户端代码, public class Callb ...

随机推荐

  1. 微信小程序看上去很美

    目前不少关于 微信小程序 的文章主要集中在两各方面:一是开发技术细节:二是怎么靠此赚钱. -- “微信小程序”所处的环境 -- 2016年初,美国号召全民学编程,包括监狱服刑人员.同样,在中国要想掌握 ...

  2. 使用cglib实现数据库框架的级联查询

    写在前面的 这一章是之前写的<手把手教你写一个Java的orm框架> 的追加内容.因为之前写的数据库框架不支持级联查询这个操作,对于有关联关系的表用起来还是比较麻烦,于是就准备把这个功能给 ...

  3. 了解java虚拟机—JVM相关参数设置(2)

    1.   JVM相关参数设置 JVM相关配置 -XX:+PrintGC 两次次YoungGC,两次FullGC. -XX:+PrintGCDetails 打印GC时的内存,并且在程序结束时打印堆内存使 ...

  4. SpringBoot整合Druid数据连接池

    SpringBoot整合Druid数据连接池 Druid是什么? Druid是Alibaba开源的的数据库连接池.Druid能够提供强大的监控和扩展功能. 在哪里下载druid maven中央仓库: ...

  5. Java - “JUC”锁

    [Java并发编程实战]-----“J.U.C”:锁,lock   在java中有两种方法实现锁机制,一种是在前一篇博客中([java7并发编程实战]-----线程同步机制:synchronized) ...

  6. 'QuerySet' object has no attribute '_meta'

    'QuerySet' object has no attribute '_meta' 对象列表没有'_meta'属性 单独的对象才有, 忘记加first了 edit_obj = models.Role ...

  7. django-强大的ORM

    一.ORM简介 (对象关系映射:object relationship mapping) MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的 ...

  8. 使用LINQ查询数据实例和理解

    使用LINQ查询数据实例和理解 var contacts= from customer in db.Customers where customer.Name.StartsWith("A&q ...

  9. JavaSE——序列化和反序列化

    序列化: 序列化对应写的操作.(读与写都是站在应用的角度上) 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化.可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间 ...

  10. Expo大作战(二十五)--expo sdk api之Admob

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...