WCF接口实现

本文详细介绍了Windows Communication Foundation (WCF) 的服务端与客户端通信过程,包括服务接口定义、服务实现、服务启动及客户端调用的完整流程。通过示例展示了如何在服务端定义接口和实现类,以及在客户端如何配置通道工厂调用服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序之间的通信有很多方法,API,Socket,共享路径的配置文档等等,

Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台。

整合了原有的windows通讯的 .net Remoting,WebService,Socket的机制,并融合有HTTPFTP的相关技术。

简单的归结为四大部分

1>.网络服务的协议,即用什么网络协议开放客户端接入。

2>.业务服务的协议,即声明服务提供哪些业务。

3>.数据类型声明,即对客户端与服务器端通信的数据部分进行一致化。

4>.传输安全性相关的定义。

下面直接看一个例子:(服务端)

 

1.定义一个WCF接口名称未Ichangeline

  // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IStaffLoginCheckService”。
    [ServiceContract] //服务协定定义
    public interface IChangeline
    {

        [OperationContract] // 操作服务定义

        string EsopCheckOk();

        [OperationContract]
        string HelloWorld();

    } 

2.定义一个类实现接口名称Changeline

 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“StaffLoginCheckService”。
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
    public class Changeline : IChangeline
    {
       public string HelloWorld()
        {
            string result = "123456";
            return result;
        }

}

3.开通WCF所需要的服务,也可以从VS直接添加WCF服务

   #region 启动WCF服务
        private void OpenWcfService()
        {
            try
            {
                var changeline = new Changeline(bendview);
                host = new ServiceHost(changeline, new Uri("http://localhost:8734/MyService/"));
                //这是我们服务的地址
                host.AddServiceEndpoint(typeof(IChangeline), new BasicHttpBinding(), string.Empty);
                host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
                //mex元数据的地址
                host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(),
                    "mex");
                host.Open();
                var port = "8734"; //获取端口号
                var inname = "Changeline"; //打开端口号的名称
                var str = " netsh advfirewall firewall add rule name=" + inname +
                          " dir=in action=allow protocol=TCP localport= " + port;
                var pro = new Process(); //实例化进程
                pro.StartInfo.FileName = "cmd.exe"; //设置要运行的程序文件
                pro.StartInfo.UseShellExecute = false; //是否使用操作系统shell程序启动
                pro.StartInfo.RedirectStandardInput = true; //是否接受来自应用程序的调用
                pro.StartInfo.RedirectStandardOutput = true; //是否接受来自应用程序的输出信息
                pro.StartInfo.RedirectStandardError = true; //是否接受重定向错误信息
                pro.StartInfo.CreateNoWindow = true; //不显示窗口信息
                pro.Start(); //启动程序

                //向cmd窗口发送输入信息
                pro.StandardInput.WriteLine(str + "&exit");

                pro.StandardInput.AutoFlush = true;
                pro.WaitForExit(); //等待程序运行完退出程序
                pro.Close(); //关闭进程
            }
            catch (Exception ex)
            {
                Tool.Log.Error("WCF开起失败:" + ex.Message);
            }
            CheckWCFServerTh = new Thread(WCF_HostCheck);
            CheckWCFServerTh.IsBackground = true;
            CheckWCFServerTh.Start();
        }
        void WCF_HostCheck(object o)
        {
            //Closed 指示通信对象已关闭,且不再可用。
            //Closing 指示通信对象正转换到 Closed 状态。
            //Created 指示通信对象已实例化且可配置,但尚未打开或无法使用。
            //Faulted 指示通信对象发生错误,无法恢复且不再可用。
            //Opened 指示通信对象目前已打开,且随时可供使用。
            //Opening 指示通信对象正从 Created 状态转换到 Opened 状态。
            while (true)
            {
                try
                {
                    if (!(host.State == CommunicationState.Opened || host.State == CommunicationState.Opening))
                    {
                        var changeline = new Changeline(bendview);
                        host = new ServiceHost(changeline, new Uri("http://localhost:8734/MyService/"));
                        //这是我们服务的地址
                        host.AddServiceEndpoint(typeof(IChangeline), new BasicHttpBinding(), string.Empty);
                        host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
                        //mex元数据的地址
                        host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(),
                            "mex");
                        host.Open();

                        var port = "8734"; //获取端口号
                        var inname = "Changeline"; //打开端口号的名称
                        var str = " netsh advfirewall firewall add rule name=" + inname +
                                  " dir=in action=allow protocol=TCP localport= " + port;
                        var pro = new Process(); //实例化进程
                        pro.StartInfo.FileName = "cmd.exe"; //设置要运行的程序文件
                        pro.StartInfo.UseShellExecute = false; //是否使用操作系统shell程序启动
                        pro.StartInfo.RedirectStandardInput = true; //是否接受来自应用程序的调用
                        pro.StartInfo.RedirectStandardOutput = true; //是否接受来自应用程序的输出信息
                        pro.StartInfo.RedirectStandardError = true; //是否接受重定向错误信息
                        pro.StartInfo.CreateNoWindow = true; //不显示窗口信息
                        pro.Start(); //启动程序
                        //向cmd窗口发送输入信息
                        pro.StandardInput.WriteLine(str + "&exit");
                        pro.StandardInput.AutoFlush = true;
                        pro.WaitForExit(); //等待程序运行完退出程序
                        pro.Close(); //关闭进程
                    }
                }
                catch (Exception ex)
                {
                    Tool.Log.Error("WCF开起失败:" + ex.Message);
                }
                Thread.Sleep(3000);
            }
        }
        #endregion

二.客户端的程序

1.配置好通道工厂,为客户端创立独立通道,为获取接口配置程序可以创建一个类(WcfChannelFactory)

 /// <summary>
     /// 使用ChannelFactory为wcf客户端创建独立通道
     /// </summary>
     public class WcfChannelFactory
     {
         public WcfChannelFactory()
         {
         }

        /// <summary>
        /// 执行方法   WSHttpBinding
        /// </summary>
        /// <typeparam name="T">服务接口</typeparam>
        /// <param name="uri">wcf地址</param>
        /// <param name="methodName">方法名</param>
        /// <param name="args">参数列表</param>
        public static object ExecuteMetod<T>(string uri, string methodName, params object[] args)
         {
             //BasicHttpBinding binding = new BasicHttpBinding();   //出现异常:远程服务器返回错误: (415) Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'.。
             WSHttpBinding binding = new WSHttpBinding();
             EndpointAddress endpoint = new EndpointAddress(uri);
 
             using (ChannelFactory<T> channelFactory = new ChannelFactory<T>(binding, endpoint))
             {
                 T instance = channelFactory.CreateChannel();
                 using (instance as IDisposable)
                 {
                     try
                     {
                         Type type = typeof(T);
                         MethodInfo mi = type.GetMethod(methodName);
                         return mi.Invoke(instance, args);
                     }
                     catch (TimeoutException)
                     {
                         (instance as ICommunicationObject).Abort();
                         throw;
                     }
                     catch (CommunicationException)
                     {
                         (instance as ICommunicationObject).Abort();
                         throw;
                     }
                     catch (Exception vErr)
                     {
                         (instance as ICommunicationObject).Abort();
                         throw;
                     }
                 }
             }
         }
 
 
         //nettcpbinding 绑定方式
         public static object ExecuteMethod<T>(string pUrl, string pMethodName,params object[] pParams)
         {
                 EndpointAddress address = new EndpointAddress(pUrl);
                 Binding bindinginstance = null;
                 BasicHttpBinding ws = new BasicHttpBinding();
                 ws.MaxReceivedMessageSize = 20971520;
                 bindinginstance = ws;
                 using (ChannelFactory<T> channel = new ChannelFactory<T>(bindinginstance, address))
                 {
                     T instance = channel.CreateChannel();
                     using (instance as IDisposable)
                     {
                         try
                         {
                             Type type = typeof(T);
                             MethodInfo mi = type.GetMethod(pMethodName);
                             return mi.Invoke(instance, pParams);
                         }
                         catch (TimeoutException)
                         {
                             (instance as ICommunicationObject).Abort();
                             throw;
                         }
                         catch (CommunicationException)
                         {
                             (instance as ICommunicationObject).Abort();
                             throw;
                         }
                         catch (Exception vErr)
                         {
                             (instance as ICommunicationObject).Abort();
                             throw;
                         }
                     }
                 }
         }
     }

2.调用WcfChannelFactory,获取接口数据

调用时需要把服务端开的接口添加到本程序中,

   public void Statedeal()
        {
            try
            {

                string result = WcfChannelFactory.ExecuteMethod<IChangeline>("http://localhost:8734/MyService/", "EsopCheckOk").ToString();
              
                MessageBox.Show(result.ToString());
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());

            }
        }

此时整个的服务端与客户端都可以实现了,如果客户端程序中也含有wcf服务程序(也会发布WCF服务,也作为服务端),并且接口名称与服务端(本客户端的服务端)的接口名称相同,那就必须保证服务端提供的接口名称与客户端定义的接口名称不同,或者相同名称在不同的程序集下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值