zoukankan      html  css  js  c++  java
  • 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.  }  
  • 相关阅读:
    POJ-1502-MPI Maelstrom
    POJ-3259-Wormholes
    【BZOJ4399】—膜法少女LJJ(线段树合并)
    省选模板复习—【计算几何】
    【BZOJ2115】【WC2011】—Xor(线性基)
    【洛谷P5290】【十二省联考2019】春节十二响(贪心+启发式合并)
    【BZOJ5461】 【PKUWC2018】—Minimax(线段树合并优化dp)
    【LOJ#3043】【洛谷P5280】【ZJOI2019】—线段树(计数dp+线段树)
    【省选模拟】—猎人杀(概率dp)
    【BZOJ4828】【HNOI2017】—大佬(LmyAKIOI!)
  • 原文地址:https://www.cnblogs.com/yelanggu/p/8311209.html
Copyright © 2011-2022 走看看