构建 WCF 路由器 part 2 from MSDN
[ServiceContract(Namespace = "http://www.thatindigogirl.com/samples/2008/01")] public interface IServiceA {[OperationContract]string SendMessage(string msg); } [ServiceContract(Namespace = "http://www.thatindigogirl.com/samples/2008/01")] public interface IServiceB {[OperationContract]string SendMessage(string msg); } public class ServiceA : IServiceA {...} public class ServiceB : IServiceB{...}
static public IDictionary<string, string> RegistrationList = new Dictionary<string, string>();RegistrationList.Add("http://www.thatindigogirl.com/samples/2008/01/IServiceA", "ServiceA"); RegistrationList.Add("http://www.thatindigogirl.com/samples/2008/01/IServiceB", "ServiceB");
string contractNamespace = requestMessage.Headers.Action.Substring(0, requestMessage.Headers.Action.LastIndexOf("/"));string configurationName = RouterService.RegistrationList[contractNamespace];using (ChannelFactory<IRouterService> factory = new ChannelFactory<IRouterService>(configurationName)) {...}
- 与在数据库中非常相似,将约定映射到服务可以简化配置并支持多个路由器实例。
- 服务约定无法在多个服务类型上实现,除非消息可由实现该约定的某个服务进行处理。
- 如果服务器场中有多个服务实例,则每个端点的配置都应映射到一个虚拟地址,然后物理负载平衡器会进行相应分发。
- 除了面向应用程序服务的消息外,不支持包含 action 标头的消息。
<service behaviorConfiguration="serviceBehavior" name="MessageManager.ServiceA"><endpoint address="http://localhost:8010/RouterService"binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="IServiceA" listenUri="ServiceA"><headers><Route xmlns="http://www.thatindigogirl.com/samples/2008/01">http://www.thatindigogirl.com/samples/2008/01/IServiceA</Route></headers></endpoint> </service>
<client><endpoint address="http://localhost:8010/RouterService" binding="wsHttpBinding" bindingConfiguration="wsHttp"contract="localhost.IServiceA" ><headers><Route xmlns="http://www.thatindigogirl.com/samples/2008/01">http://www.thatindigogirl.com/samples/2008/01/IServiceA</Route></headers></endpoint> </client>
string contractNamespace = requestMessage.Headers.GetHeader<string>("Route", "http://www.thatindigogirl.com/samples/2008/01");
- 实现路由器的服务注册约定并向防火墙后的应用程序服务公开该端点。
- 维护路由器的注册列表。
- 每次初始化 ServiceHost 后,使其向路由器注册服务端点。
- 每次 ServiceHost 出现错误或关闭时,取消向路由器注册服务端点。
[ServiceContract(Namespace = "http://www.thatindigogirl.com/samples/2008/01")] public interface IRegistrationService {[OperationContract]void Register(RegistrationInfo regInfo);[OperationContract]void Unregister(RegistrationInfo regInfo); }[DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2008/01")] public class RegistrationInfo {[DataMember(IsRequired = true, Order = 1)]public string Address { get; set; }[DataMember(IsRequired = true, Order = 2)]public string ContractName { get; set; }[DataMember(IsRequired = true, Order = 3)]public string ContractNamespace { get; set; }public override int GetHashCode() {return this.Address.GetHashCode() + this.ContractName.GetHashCode() + this.ContractNamespace.GetHashCode();} }
// registration list static public IDictionary<int, RegistrationInfo> RegistrationList = new Dictionary<int, RegistrationInfo>();// to register if (!RouterService.RegistrationList.ContainsKey(regInfo.GetHashCode())) {RouterService.RegistrationList.Add(regInfo.GetHashCode(), regInfo);}// to unregisterif (RouterService.RegistrationList.ContainsKey(regInfo.GetHashCode())) {RouterService.RegistrationList.Remove(regInfo.GetHashCode());}
string contractNamespace = requestMessage.Headers.Action.Substring(0, requestMessage.Headers.Action.LastIndexOf("/"));// get a list of all registered service entries for // the specified contract var results = from item in RouterService.RegistrationListwhere item.Value.ContractNamespace.Contains(contractNamespace)select item;int index = 0; // find the next address used ...// create the channel RegistrationInfo regInfo = results.ElementAt<KeyValuePair<int, RegistrationInfo>>(index).Value;Uri addressUri = new Uri(regInfo.Address); Binding binding = ConfigurationUtility.GetRouterBinding (addressUri.Scheme); EndpointAddress endpointAddress = new EndpointAddress(regInfo.Address);ChannelFactory<IRouterService> factory = new ChannelFactory<IRouterService>(binding, endpointAddress) // forward message to the service ...
<endpoint address="net.tcp://localhost:9000/ServiceA" contract=" IServiceA" binding="netTcpBinding"listenUriMode="Unique"/>
net.tcp://localhost:64544/ServiceA http://localhost:8000/ServiceA/66e9c367-b681-4e4f-8d12-80a631b7bc9b net.pipe://localhost/ServiceA/6660c07e-c9f5-450b-8d40-693ad1a71c6e
Uri httpBase = new Uri(string.Format("http://localhost:{0}", FindFreePort())); Uri tcpBase = new Uri(string.Format("net.tcp://localhost:{0}", FindFreePort())); Uri netPipeBase = new Uri(string.Format("net.pipe://localhost/{0}", Guid.NewGuid().ToString()));ServiceHost host = new ServiceHost(typeof(ServiceA), httpBase, tcpBase, netPipeBase);
// operation [OperationContract] SendMessageResponse SendMessage(SendMessageRequest message);// message contract [MessageContract] public class SendMessageRequest {[MessageHeader]public string LicenseKey { get; set; }[MessageBodyMember]public string Message { get; set; } }
string licenseKey = requestMessage.Headers.GetHeader<string>("LicenseKey", "http://www.thatindigogirl.com/samples/2008/01");
XmlDictionaryReader bodyReader = requestMessage.GetReaderAtBodyContents();
MessageBuffer messageBuffer = requestMessage.CreateBufferedCopy(int.MaxValue); Message messageCopy = messageBuffer.CreateMessage(); XmlDictionaryReader bodyReader = messageCopy.GetReaderAtBodyContents();XmlDocument doc = new XmlDocument(); doc.Load(bodyReader); XmlNodeList elements = doc.GetElementsByTagName("LicenseKey"); string licenseKey = elements[0].InnerText;
- ProcessMessage 现在是单向操作。
- 服务约定需要会话并包含相关的回调约定。重要的是,您应该注意到这不要求客户端实现回调;这是在路由器内部执行的。
- 回调约定有一个单向方法,可接收从路由器调用到应用程序服务的响应。还请注意,服务并不知道其响应将发送到回调信道;它们可以是请求-答复消息。
[ServiceContract(Namespace = "http://www.thatindigogirl.com/samples/2008/01", SessionMode = SessionMode.Required, CallbackContract = typeof(IDuplexRouterCallback))]public interface IDuplexRouterService {[OperationContract(IsOneWay=true, Action = "*")]void ProcessMessage(Message requestMessage); }[ServiceContract(Namespace = "http://www.thatindigogirl.com/samples/2008/01", SessionMode = SessionMode.Allowed)] public interface IDuplexRouterCallback {[OperationContract(IsOneWay=true, Action = "*")]void ProcessMessage(Message requestMessage); }
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple, AddressFilterMode=AddressFilterMode.Any, ValidateMustUnderstand=false)]public class DuplexRouterService : IDuplexRouterService, IDisposable {object m_duplexSessionLock = new object();IDuplexRouterService m_duplexSession;public void ProcessMessage(Message requestMessage) {lock (this.m_duplexSessionLock) {if (this.m_duplexSession == null) {IDuplexRouterCallback callback = OperationContext.Current.GetCallbackChannel<IDuplexRouterCallback>();DuplexChannelFactory<IDuplexRouterService> factory = new DuplexChannelFactory<IDuplexRouterService>(new InstanceContext(null, new DuplexRouterCallback(callback)), "serviceEndpoint");factory.Endpoint.Behaviors.Add(new MustUnderstandBehavior(false));this.m_duplexSession = factory.CreateChannel();}}this.m_duplexSession.ProcessMessage(requestMessage);}public void Dispose() {if (this.m_duplexSession != null) {try {ICommunicationObject obj = this.m_duplexSession as ICommunicationObject;if (obj.State == CommunicationState.Faulted)obj.Abort();elseobj.Close();}catch {}}} }public class DuplexRouterCallback : IDuplexRouterCallback {private IDuplexRouterCallback m_clientCallback;public DuplexRouterCallback(IDuplexRouterCallback clientCallback) {m_clientCallback = clientCallback;}public void ProcessMessage(Message requestMessage) {this.m_clientCallback.ProcessMessage(requestMessage);} }
转载于:https://www.cnblogs.com/EasyLive2006/archive/2009/10/26/1590196.html
构建 WCF 路由器 part 2 from MSDN相关推荐
- 【培训稿件】构建WCF面向服务的应用程序(包含ppt,源代码)
今天在整理电脑的时候,从目录中搜出了之前公司的培训演讲稿件,这个是我第一次在部门里面做内部培训,当时反映还不错.于是整理下这份稿件.大家如果有兴趣可以下载看看. 构建WCF面向服务的应用程序(ppt, ...
- 利用Iptables构建虚拟路由器
利用Iptables构建虚拟路由器 (1)修改网络类型 在VMware Workstation软件中选择"编辑→虚拟网络编辑器"菜单命令,在虚拟网络列表中选中VMnet1,将其配置 ...
- mininet构建双路由器实验
利用mininet构建下面的拓扑,并测试能否ping通: 路由器会自动生成本路由器激活端口所在网段的路由条目,即直接路由,因此要让两主机之间能ping通,只要造A, B中分别添加静态路由即可 (当然还 ...
- 使用 History API 构建 JavaScript 路由器
在本文中,我们将构建一个客户端路由系统.客户端路由是一种路由类型,用户在其中导航应用程序,即使页面的 URL 发生更改,也不会重新加载整个页面,而是显示新内容. 为了构建它,我们需要一个简单的服务器来 ...
- 在Ubuntu中安装FRR构建虚拟路由器
安装依赖关系 apt-get update apt-get install \git autoconf automake libtool make libreadline-dev texinfo \p ...
- 使用 Vanilla JavaScript 构建自定义 SPA 路由器
介绍 在本文中,我将解释如何使用 Vanilla JavaScript 构建自定义 SPA 路由器.我必须在没有任何使用框架的情况下构建一个 UI 项目,并且必须弄清楚如何处理路由,并发现您可以轻松地 ...
- WCF Membership Provider
ASP.NET 是自.NET 1.x 就已经有的技术,利用IIS+ASP.NET 搭建的网站已经有很多.针对IIS+ASP.NET 的网站模型也有很多案例,通过现在的搜索服务我们可以很轻易的获取这些内 ...
- WCF分布式开发步步为赢(0):WCF学习经验分享,如何更好地学习WCF?
WCF分布式开发学习,应该从哪里开始? 微软WCF Web服务 Web API学习群 339444457 微软ASP.NET MVC 4 Web编程群 44206115 学习WCF是不是就不需 ...
- [zz]WCF分布式开发步步为赢(0):WCF学习经验分享,如何更好地学习WCF?
WCF分布式开发学习,应该从哪里开始? 学习WCF是不是就不需要学习Enterprise Sevices(COM+).Net Remoting.Web Service(ASMX).WSE3.0和 ...
最新文章
- CentOS 配置防火墙操作实例(启、停、开、闭端口)
- 常用的图像增强处理办法
- SAP UI5 message.showMessageToast
- Akka STM –与STM Ref和Agent进行乒乓球比赛
- QT学习笔记(一):VS2013 +QT 5.8 运行、编译问题解决
- 在eclipse上搭建springBoot
- 程序员:像机器一样思考
- 第 3 章 JVM 与 GC
- android app记录执行日志 捕获奔溃异常 ,存储日志到文件
- 绝对的干货大放送:常用正则表达式收集大全
- bzoj2242: [SDOI2011]计算器
- SpringBoot 快速入门
- 暗时间--平凡与优秀间的距离
- php美颜滤镜,新手入门看这里,BeautifyFace美颜滤镜Demo中文注释
- Java控制excel,word文档只读模式
- Python自动化测试常用库整理
- oracle分区备份,oracle分区表备份,只还原1个分区
- Teamcenter Folder
- OKRs-E 让目标推进成功率提升200%
- Graphics2D(1) : 查看系统所有字体
热门文章
- 1.搭建Java+Selenium+WebDriver测试环境
- JavaScript入门3JS外置对象:Window、Document对象与DOM实例详解
- 网络安全形势严峻进入“红色警报”阶段
- 飞行出租车、超级高铁和无人驾驶车:现在开始规划是否为时过早?
- QQ和360正面交火了,有图为证
- [O2JAM劲乐团] 音乐集...
- 中国第三方支付系统目前存在的问题
- 本周总结 前端第二次作业 模仿制作百度界面
- WV.12-枚举-平面点的对称点
- 利用搜搜的问问做外链小技巧