Ответ 1
Черт! это был брандмауэр... по какой-то причине вся связь UDP была заблокирована - отключение брандмауэра решило проблему. Теперь мне нужно только выяснить правильную конфигурацию брандмауэра...
Я пытаюсь добавить ad-hoc-открытие к простой настройке службы WCF-сервиса (в настоящее время реализуется самообслуживанием в консольном приложении). Отладка с использованием VS2010 на Windows 7 и все, что я могу найти в онлайн-учебнике, но все же - клиент обнаружения просто ничего не находит. Излишне говорить, что если я открою клиента для правильной конечной точки обслуживания, я могу получить доступ к этой услуге от клиента.
код обслуживания:
using (var selfHost = new ServiceHost(typeof(Renderer)))
{
try
{
selfHost.Open();
...
selfHost.Close();
service 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;
Коллекция "endpoints" всегда выходит пустым. Я попробовал запустить службу и клиент из отладчика из командной строки из командной строки администратора - все, но безрезультатно (все на локальной машине, конечно, не в мантионе, мне нужно, чтобы она работала на вся моя подсеть)
Любая помощь будет оценена: -)
Черт! это был брандмауэр... по какой-то причине вся связь UDP была заблокирована - отключение брандмауэра решило проблему. Теперь мне нужно только выяснить правильную конфигурацию брандмауэра...
Вот пример супер простого открытия. Он не использует конфигурационный файл, это все код С#, но вы, вероятно, можете переносить концепции в файл конфигурации.
поделиться этим интерфейсом между хостом и клиентской программой (копировать в каждую программу на данный момент)
[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
Это серьезный минимум, который я мог бы придумать для примера обнаружения. Этот материал становится довольно сложным быстро.
Поскольку это первый ответ stackoverflow.com, который появляется, когда я искал "Открытие WCF", я предложил бы пример IDesign Juval Lowy: Ad-hoc Discovery. Это отличный пример обнаружения WCF с использованием UdpDiscoveryEndpoint и MEX. Если вы не знакомы с IDesign или Juval Lowy, я бы также предложил эту ссылку MSDN.