WCF接口实例介绍
Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台。
WCF整合了原有的windows通讯的 .net Remoting,WebService,Socket的机制,并融合有HTTP和FTP的相关技术。
简单的归结为四大部分
1>.网络服务的协议,即用什么网络协议开放客户端接入。
2>.业务服务的协议,即声明服务提供哪些业务。
3>.数据类型声明,即对客户端与服务器端通信的数据部分进行一致化。
4>.传输安全性相关的定义。
下面直接看一个例子:
一.服务端实例
1.定义一个WCF接口名称未Ichangeline
服务契约(ServiceContract),订定服务的定义。
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“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服务
1 #region 启动WCF服务 2 private void OpenWcfService() 3 { 4 try 5 { 6 var changeline = new Changeline(bendview); 7 host = new ServiceHost(changeline, new Uri("http://localhost:8734/MyService/")); 8 //这是我们服务的地址 9 host.AddServiceEndpoint(typeof(IChangeline), new BasicHttpBinding(), string.Empty); 10 host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 11 //mex元数据的地址 12 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), 13 "mex"); 14 host.Open(); 15 var port = "8734"; //获取端口号 16 var inname = "Changeline"; //打开端口号的名称 17 var str = " netsh advfirewall firewall add rule name=" + inname + 18 " dir=in action=allow protocol=TCP localport= " + port; 19 var pro = new Process(); //实例化进程 20 pro.StartInfo.FileName = "cmd.exe"; //设置要运行的程序文件 21 pro.StartInfo.UseShellExecute = false; //是否使用操作系统shell程序启动 22 pro.StartInfo.RedirectStandardInput = true; //是否接受来自应用程序的调用 23 pro.StartInfo.RedirectStandardOutput = true; //是否接受来自应用程序的输出信息 24 pro.StartInfo.RedirectStandardError = true; //是否接受重定向错误信息 25 pro.StartInfo.CreateNoWindow = true; //不显示窗口信息 26 pro.Start(); //启动程序 27 28 //向cmd窗口发送输入信息 29 pro.StandardInput.WriteLine(str + "&exit"); 30 31 pro.StandardInput.AutoFlush = true; 32 pro.WaitForExit(); //等待程序运行完退出程序 33 pro.Close(); //关闭进程 34 } 35 catch (Exception ex) 36 { 37 Tool.Log.Error("WCF开起失败:" + ex.Message); 38 } 39 CheckWCFServerTh = new Thread(WCF_HostCheck); 40 CheckWCFServerTh.IsBackground = true; 41 CheckWCFServerTh.Start(); 42 } 43 void WCF_HostCheck(object o) 44 { 45 //Closed 指示通信对象已关闭,且不再可用。 46 //Closing 指示通信对象正转换到 Closed 状态。 47 //Created 指示通信对象已实例化且可配置,但尚未打开或无法使用。 48 //Faulted 指示通信对象发生错误,无法恢复且不再可用。 49 //Opened 指示通信对象目前已打开,且随时可供使用。 50 //Opening 指示通信对象正从 Created 状态转换到 Opened 状态。 51 while (true) 52 { 53 try 54 { 55 if (!(host.State == CommunicationState.Opened || host.State == CommunicationState.Opening)) 56 { 57 var changeline = new Changeline(bendview); 58 host = new ServiceHost(changeline, new Uri("http://localhost:8734/MyService/")); 59 //这是我们服务的地址 60 host.AddServiceEndpoint(typeof(IChangeline), new BasicHttpBinding(), string.Empty); 61 host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 62 //mex元数据的地址 63 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), 64 "mex"); 65 host.Open(); 66 67 var port = "8734"; //获取端口号 68 var inname = "Changeline"; //打开端口号的名称 69 var str = " netsh advfirewall firewall add rule name=" + inname + 70 " dir=in action=allow protocol=TCP localport= " + port; 71 var pro = new Process(); //实例化进程 72 pro.StartInfo.FileName = "cmd.exe"; //设置要运行的程序文件 73 pro.StartInfo.UseShellExecute = false; //是否使用操作系统shell程序启动 74 pro.StartInfo.RedirectStandardInput = true; //是否接受来自应用程序的调用 75 pro.StartInfo.RedirectStandardOutput = true; //是否接受来自应用程序的输出信息 76 pro.StartInfo.RedirectStandardError = true; //是否接受重定向错误信息 77 pro.StartInfo.CreateNoWindow = true; //不显示窗口信息 78 pro.Start(); //启动程序 79 //向cmd窗口发送输入信息 80 pro.StandardInput.WriteLine(str + "&exit"); 81 pro.StandardInput.AutoFlush = true; 82 pro.WaitForExit(); //等待程序运行完退出程序 83 pro.Close(); //关闭进程 84 } 85 } 86 catch (Exception ex) 87 { 88 Tool.Log.Error("WCF开起失败:" + ex.Message); 89 } 90 Thread.Sleep(3000); 91 } 92 } 93 #endregion
二.客户端的程序
1.配置好通道工厂,为客户端创立独立通道,为获取接口配置程序可以创建一个类(WcfChannelFactory)
1 /// <summary> 2 /// 使用ChannelFactory为wcf客户端创建独立通道 3 /// </summary> 4 public class WcfChannelFactory 5 { 6 public WcfChannelFactory() 7 { 8 } 9 10 /// <summary> 11 /// 执行方法 WSHttpBinding 12 /// </summary> 13 /// <typeparam name="T">服务接口</typeparam> 14 /// <param name="uri">wcf地址</param> 15 /// <param name="methodName">方法名</param> 16 /// <param name="args">参数列表</param> 17 public static object ExecuteMetod<T>(string uri, string methodName, params object[] args) 18 { 19 //BasicHttpBinding binding = new BasicHttpBinding(); 20 WSHttpBinding binding = new WSHttpBinding(); 21 EndpointAddress endpoint = new EndpointAddress(uri); 22 23 using (ChannelFactory<T> channelFactory = new ChannelFactory<T>(binding, endpoint)) 24 { 25 T instance = channelFactory.CreateChannel(); 26 using (instance as IDisposable) 27 { 28 try 29 { 30 Type type = typeof(T); 31 MethodInfo mi = type.GetMethod(methodName); 32 return mi.Invoke(instance, args); 33 } 34 catch (TimeoutException) 35 { 36 (instance as ICommunicationObject).Abort(); 37 throw; 38 } 39 catch (CommunicationException) 40 { 41 (instance as ICommunicationObject).Abort(); 42 throw; 43 } 44 catch (Exception vErr) 45 { 46 (instance as ICommunicationObject).Abort(); 47 throw; 48 } 49 } 50 } 51 } 52 53 54 //nettcpbinding 绑定方式 55 public static object ExecuteMethod<T>(string pUrl, string pMethodName,params object[] pParams) 56 { 57 EndpointAddress address = new EndpointAddress(pUrl); 58 Binding bindinginstance = null; 59 BasicHttpBinding ws = new BasicHttpBinding(); 60 ws.MaxReceivedMessageSize = 20971520; 61 bindinginstance = ws; 62 using (ChannelFactory<T> channel = new ChannelFactory<T>(bindinginstance, address)) 63 { 64 T instance = channel.CreateChannel(); 65 using (instance as IDisposable) 66 { 67 try 68 { 69 Type type = typeof(T); 70 MethodInfo mi = type.GetMethod(pMethodName); 71 return mi.Invoke(instance, pParams); 72 } 73 catch (TimeoutException) 74 { 75 (instance as ICommunicationObject).Abort(); 76 throw; 77 } 78 catch (CommunicationException) 79 { 80 (instance as ICommunicationObject).Abort(); 81 throw; 82 } 83 catch (Exception vErr) 84 { 85 (instance as ICommunicationObject).Abort(); 86 throw; 87 } 88 } 89 } 90 } 91 }
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服务,也作为服务端),并且接口名称与服务端(本客户端的服务端)的接口名称相同,那就必须保证服务端提供的接口名称与客户端定义的接口名称不同,或者相同名称在不同的程序集下。