Winfrom 使用WCF 实现双工通讯

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

  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.  }  
posted @ 2018-01-18 17:06  野狼谷  阅读(588)  评论(1编辑  收藏  举报