Service Host:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; namespace Test.WCF.ServiceBus.Host.Service { [ServiceContract(Namespace = "urn:ps")] interface IProblemSolver { [OperationContract] int AddNumbers(int a, int b); } interface IProblemSolverChannel : IProblemSolver, IClientChannel { } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test.WCF.ServiceBus.Host.Service { class ProblemSolver : IProblemSolver { public int AddNumbers(int a, int b) { return a + b; } } }

using Microsoft.ServiceBus; using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; using Test.WCF.ServiceBus.Host.Service; namespace Test.WCF.ServiceBus.Host { class Program { static void Main(string[] args) { ServiceHost sh = new ServiceHost(typeof(ProblemSolver)); sh.AddServiceEndpoint( typeof(IProblemSolver), new NetTcpBinding(), "net.tcp://localhost:9358/***Relay Name***"); sh.AddServiceEndpoint( typeof(IProblemSolver), new NetTcpRelayBinding(), ServiceBusEnvironment.CreateServiceUri("sb", "***Service Bus Name***", "***Relay Name***")) .Behaviors.Add(new TransportClientEndpointBehavior { TokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner", "***Service Bus Token***") }); sh.Open(); Console.WriteLine("Press ENTER to close"); Console.ReadLine(); sh.Close(); } } }
Service Client:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; namespace Test.WCF.ServiceBus.Client { [ServiceContract(Namespace = "urn:ps")] interface IProblemSolver { [OperationContract] int AddNumbers(int a, int b); } interface IProblemSolverChannel : IProblemSolver, IClientChannel { } }

using Microsoft.ServiceBus; using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace Test.WCF.ServiceBus.Client { class Program { public static ChannelFactory<IMediaServicesManagementServiceChannel> testCF=null; static void Main(string[] args) { Retry( () => { bool flag = false; var cf = new ChannelFactory<IMediaServicesManagementServiceChannel>( new NetTcpRelayBinding(), new EndpointAddress(ServiceBusEnvironment.CreateServiceUri("sb", "***Service Bus Name***", "***Relay Name***"))); cf.Endpoint.Behaviors.Add(new TransportClientEndpointBehavior { TokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner", "***Service Bus Token***") }); var ch1 = cf.CreateChannel(); try { Console.WriteLine(ch1.AddNumbers(3, 4)); flag = true; } catch { ch1.Abort(); flag = false; } finally { if (ch1 != null) { ch1.Close(); } } return flag; }, 5); Console.WriteLine("Press ENTER to close"); Console.ReadLine(); } public static void Retry(Func<bool> task, int times) { bool flag = false; for (int i = 0; i < times; i++ ) { flag = task(); if(flag==true) { break; } } } } }
这里在client端加入了Retry的逻辑以用于由于网络不稳定或其他原因造成的Host Service Faulted State的情形。
同时要注意,WCF创建的Channel是Fault State时,在调用.Close()之前, 要先调用.Abort().
Reference Links:
http://jeffbarnes.net/blog/post/2007/04/24/wcf-your-proxy-can-only-fault-once.aspx
http://blog.tallan.com/2009/05/06/recover-from-a-wcf-service-fault/