Ad Hoc Discovery
Service (add "UdpDiscoveryEndpoint")
// Add ServiceDiscoveryBehavior
svcHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
// Add a UdpDiscoveryEndpoint
svcHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Client (use "DiscoveryClient")
DiscoveryClient client = new DiscoveryClient(new UdpDiscoveryEndpoint());
FindCriteria criteria = new FindCriteria(typeof(Service.ISocialStatus));
FindResponse findResult = client.Find(criteria);
foreach (var item in findResult.Endpoints)
{
Console.WriteLine(item.Address);
}
Console.WriteLine();
var address = findResult.Endpoints.First(ep => ep.Address.Uri.Scheme == "http").Address;
Console.WriteLine(address);
var factory = new ChannelFactory<Service.ISocialStatus>(new BasicHttpBinding(), address);
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.UpdateStatus("abc"));
((ICommunicationObject)proxy).Close();
http://msdn.microsoft.com/en-us/library/ee816866.aspx
Termination criteria include:
- Duration - The maximum time to wait for replies from services on the network. The default duration is 20 seconds.
- MaxResults - The maximum number of replies to wait for. If MaxResults replies are received before Duration has elapsed, the find operation ends.
Discovery + Scope
The use of discovery implies a somewhat loose relationship between the client and the service or services it discovers. This presents another set of problems—how can the client know it has discovered the right endpoint? When multiple compatible endpoints are discovered, which one should the client invoke?
Clearly, there is a need for some mechanism that will help the client filter the results of discovery. This is exactly what scopes are about. A scope is merely a valid URL associated with the endpoint. The service can associate a scope or even multiple scopes with each of its endpoints. The scopes are bundled along with the addresses in the response to the discovery request. In turn, the client can filter the discovered addresses based on the scopes found or, better yet, try to find only relevant scopes in the first place.
For example, suppose for a given contract you have multiple implementations. You have the operational mode used in production and the simulation mode used in testing or diagnostics. Using scopes, the client can pick and choose the correct implementation type needed, and different clients never conflict with one another by consuming one another’s services.
e.g.:
Service (Endpoint + Discovery Scope)
<system.serviceModel>
<services>
<service name="Service.SocialStatus">
<endpoint address="http://localhost:12345/GetMessage" contract="Service.ISocialStatus"
binding="wsHttpBinding" behaviorConfiguration="DiscoveryBehavior"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="DiscoveryBehavior">
<endpointDiscovery>
<scopes>
<add scope="http://localhost:12345/GetMessage"/>
</scopes>
</endpointDiscovery>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Client (FindCriteria + Scope)
DiscoveryClient client = new DiscoveryClient(new UdpDiscoveryEndpoint());
FindCriteria criteria = new FindCriteria(typeof(Service.ISocialStatus));
Uri discoveryScope = new Uri("http://localhost:12345/GetMessage");
criteria.Scopes.Add(discoveryScope);
FindResponse findResult = client.Find(criteria);
foreach (var item in findResult.Endpoints)
{
Console.WriteLine(item.Address);
}
Service Announcement
Service (Add "UdpAnnouncementEndpoint" at Service Behavior)
ServiceDiscoveryBehavior serviceDiscoveryBehavior = new ServiceDiscoveryBehavior();
serviceDiscoveryBehavior.AnnouncementEndpoints.Add(new UdpAnnouncementEndpoint());
svcHost.Description.Behaviors.Add(serviceDiscoveryBehavior);
// Create an AnnouncementService instance
AnnouncementService announcementService = new AnnouncementService();
// Subscribe the announcement events
announcementService.OnlineAnnouncementReceived += OnOnlineEvent;
announcementService.OfflineAnnouncementReceived += OnOfflineEvent;
// Create ServiceHost for the AnnouncementService
using (ServiceHost announcementServiceHost = new ServiceHost(announcementService))
{
// Listen for the announcements sent over UDP multicast
announcementServiceHost.AddServiceEndpoint(new UdpAnnouncementEndpoint());
announcementServiceHost.Open();
Console.WriteLine("Press <ENTER> to terminate.");
Console.ReadLine();
}
static void OnOnlineEvent(object sender, AnnouncementEventArgs e)
{
Console.WriteLine("Received an online announcement from {0}",
e.EndpointDiscoveryMetadata.Address);
}
static void OnOfflineEvent(object sender, AnnouncementEventArgs e)
{
Console.WriteLine("Received an offline announcement from {0}",
e.EndpointDiscoveryMetadata.Address);
}