Winfrom 使用WCF 实现双工通讯
实现双工通讯主要分三步。
- 通信接口的定义;
- 被调用接口的实现
- 双工通道的建立
请先引用DLL(CSDN的代码编辑器真尼玛蛋疼)
整个解决方案的结构
1、通信接口的定义;
服务端调用客户端接口IServerCallClient
- /// <summary>
- /// 服务器调用客户端接口
- /// </summary>
- public interface IServerCallClient
- {
- /// <summary>
- /// 服务器读取客户端的IP
- /// </summary>
- /// <returns></returns>
- [OperationContract]
- IPEndPoint ServerRequestCLientIP();
- /// <summary>
- /// 服务器发送消息给客户端
- /// </summary>
- /// <param name="text"></param>
- [OperationContract]
- void ServerSayMSG(string text);
- }
    /// <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
- <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>
<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、被调用接口的实现
客户端实现服务端接口的类:
- class ServerCallClient :IServerCallClient
- {
- public IPEndPoint ServerRequestCLientIP()
- {
- var ip =new IPEndPoint(IPAddress.Any,10086);
- return ip;
- }
- public void ServerSayMSG(string text)
- {
- File.AppendAllText("收到的数据", text);
- }
- }
    class ServerCallClient :IServerCallClient
    {
        public IPEndPoint ServerRequestCLientIP()
        {
            var ip =new IPEndPoint(IPAddress.Any,10086);
            return ip;
        }
        public void ServerSayMSG(string text)
        {
            File.AppendAllText("收到的数据", text);
        }
    }
服务端实现客户端接口的类
- /// <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
- }
    /// <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、双工通道的建立
服务端通道的建立- 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);
            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);
客户端通道的建立- var rand = new Random();
- InstanceContext context = new InstanceContext(new ServerCallClient());//指定回调的类
- WSDualHttpBinding binding = new WSDualHttpBinding() { ClientBaseAddress = new Uri($"http://localhost:{rand.Next(10000, 20000)}") };//指定客户端地址;
- using (DuplexChannelFactory proxy = new DuplexChannelFactory(context, binding))//创建通道管理器
- {
- IClientCallServer client = proxy.CreateChannel(new EndpointAddress("http://localhost:12345"));// 创建用于将消息发送到特定终结点地址的服务的通道client.ClientRequestTime();
- client.ClientSayToServer("尼玛");
- }
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号