2011-07-21 72 views
14

我想添加臨時發現到一個簡單的WCF服務客戶端設置(目前由控制檯應用程序中的自託管實現)。在Windows 7上使用VS2010進行調試,並在網上教程中做任何我能找到的事情,但仍然 - 發現客戶端根本找不到任何東西。不用說,如果我打開一個客戶端到正確的服務端點,我可以從客戶端訪問服務。WCF發現根本不起作用

服務代碼:

using (var selfHost = new ServiceHost(typeof(Renderer))) 
{ 
    try 
    { 
     selfHost.Open(); 
     ... 
     selfHost.Close(); 

服務的app.config:

<?xml version="1.0"?> 
<configuration> 
    <system.serviceModel> 
    <services> 
     <service name="TestApp.Renderer"> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:9000" /> 
      </baseAddresses> 
     </host> 
     <endpoint address="ws" binding="wsHttpBinding" contract="TestApp.IRenderer"/> 
     <endpoint kind="udpDiscoveryEndpoint"/> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <serviceDiscovery/> 
      <serviceMetadata httpGetEnabled="True"/> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 
</configuration> 

客戶端發現代碼:

DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); 
var criteria = new FindCriteria(typeof(IRenderer)) { Duration = TimeSpan.FromSeconds(5) }; 
var endpoints = discoveryClient.Find(criteria).Endpoints; 

的 '端點' 收集永遠是空的。我試過從調試器,從命令行,從管理命令行運行服務和客戶端 - 一切,但無濟於事(所有在本地機器上,當然,不要手動我需要它運行我的整個子網最終)

任何幫助:-)

+0

我也嘗試在serviceDiscovery行爲中添加公告端點 - 這也沒有幫助 – kbo

+0

是否有客戶端的任何app.config信息? –

+0

也有你試過添加一個範圍? –

回答

3

該死!它是防火牆......出於某種原因,所有UDP通信都被阻止 - 禁用防火牆解決了這個問題。現在我只需要找出正確的防火牆配置...

+0

你有沒有想過如何配置防火牆?我有同樣的問題。 – odyth

+1

是發現依靠UDP Blast來定位服務 –

35

意識到這裏是一個超級簡單的發現範例。它不使用配置文件,它是所有的c#代碼,但您可能將概念移植到配置文件。

共享主機和客戶端程序之間的接口(複製到每一個程序現在)

[ServiceContract] 
public interface IWcfPingTest 
{ 
    [OperationContract] 
    string Ping(); 
} 

把這個代碼把這個代碼在客戶端程序的主機程序

public class WcfPingTest : IWcfPingTest 
{ 
    public const string magicString = "djeut73bch58sb4"; // this is random, just to see if you get the right result 
    public string Ping() {return magicString;} 
} 
public void WcfTestHost_Open() 
{ 
    string hostname = System.Environment.MachineName; 
    var baseAddress = new UriBuilder("http", hostname, 7400, "WcfPing"); 
    var h = new ServiceHost(typeof(WcfPingTest), baseAddress.Uri); 

    // enable processing of discovery messages. use UdpDiscoveryEndpoint to enable listening. use EndpointDiscoveryBehavior for fine control. 
    h.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); 
    h.AddServiceEndpoint(new UdpDiscoveryEndpoint()); 

    // enable wsdl, so you can use the service from WcfStorm, or other tools. 
    var smb = new ServiceMetadataBehavior(); 
    smb.HttpGetEnabled = true; 
    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; 
    h.Description.Behaviors.Add(smb); 

    // create endpoint 
    var binding = new BasicHttpBinding(BasicHttpSecurityMode.None); 
    h.AddServiceEndpoint(typeof(IWcfPingTest) , binding, ""); 
    h.Open(); 
    Console.WriteLine("host open"); 
} 

private IWcfPingTest channel; 
public Uri WcfTestClient_DiscoverChannel() 
{ 
    var dc = new DiscoveryClient(new UdpDiscoveryEndpoint()); 
    FindCriteria fc = new FindCriteria(typeof(IWcfPingTest)); 
    fc.Duration = TimeSpan.FromSeconds(5); 
    FindResponse fr = dc.Find(fc); 
    foreach(EndpointDiscoveryMetadata edm in fr.Endpoints) 
    { 
    Console.WriteLine("uri found = " + edm.Address.Uri.ToString()); 
    } 
    // here is the really nasty part 
    // i am just returning the first channel, but it may not work. 
    // you have to do some logic to decide which uri to use from the discovered uris 
    // for example, you may discover "127.0.0.1", but that one is obviously useless. 
    // also, catch exceptions when no endpoints are found and try again. 
    return fr.Endpoints[0].Address.Uri; 
} 
public void WcfTestClient_SetupChannel() 
{ 
    var binding = new BasicHttpBinding(BasicHttpSecurityMode.None); 
    var factory = new ChannelFactory<IWcfPingTest>(binding); 
    var uri = WcfTestClient_DiscoverChannel(); 
    Console.WriteLine("creating channel to " + uri.ToString()); 
    EndpointAddress ea = new EndpointAddress(uri); 
    channel = factory.CreateChannel(ea); 
    Console.WriteLine("channel created"); 
    //Console.WriteLine("pinging host"); 
    //string result = channel.Ping(); 
    //Console.WriteLine("ping result = " + result); 
} 
public void WcfTestClient_Ping() 
{ 
    Console.WriteLine("pinging host"); 
    string result = channel.Ping(); 
    Console.WriteLine("ping result = " + result); 
} 

在主機上,只需調用WcfTestHost_Open()函數,然後永遠睡覺或者其他的東西。

在客戶端上運行這些函數。主持人需要一段時間才能打開,所以這裏有幾個延遲。

System.Threading.Thread.Sleep(8000); 
this.server.WcfTestClient_SetupChannel(); 
System.Threading.Thread.Sleep(2000); 
this.server.WcfTestClient_Ping(); 

主機輸出應該像

host open 

客戶端的輸出應該看起來像

uri found = http://wilkesvmdev:7400/WcfPing 
creating channel to http://wilkesvmdev:7400/WcfPing 
channel created 
pinging host 
ping result = djeut73bch58sb4 

這是認真的最低我能想出一個發現的例子。這些東西變得非常複雜。

+4

偉大的職位。我喜歡WCF的所有代碼最小示例! – Peladao

1

因爲這是我搜索'WCF發現'時出現的第一個stackoverflow.com答案,我會建議IDesign Juval Lowy示例:Ad-hoc Discovery。這是使用UdpDiscoveryEndpoint和MEX的WCF Discovery的一個很好的例子。如果你不熟悉IDesign或Juval Lowy,我也會建議這個MSDN link