Exercise 4: Service Discovery

In this exercise, you will add an ad hoc discovery mechanism to the DiscoveryChat program using System.ServiceModel.Discovery, an implementation of the WS-Discovery protocol. In order for a service to be discoverable in an ad hoc manner, it needs to respond to incoming probe messages. Ad hoc discovery implies that these probe messages come in through a well-known port over UDP multicast.

Task 0 – Opening the Solution

This exercise uses a new begin solution.

  1. Open the starting solution for Exercise 4 located under the Source\Ex4-ServiceDiscovery\Begin (choosing the folder that matches the language of your preference.) Use it as the starting point for this exercise.
  2. Press CTRL+SHIFT+B to build the solution.

Task 1 – Configuring Service Discovery for the DiscoveryChat Application

DiscoveryChat is a chat application that automatically discovers users on the network using ad hoc or managed discovery via a proxy.

Figure 12

Two simple chat windows with no discovery enabled

The first thing you need to do is to enable discovery in the simple chat application.

  1. To enable discovery, you need to add a service behavior on the service that will be discoverable. Open the App.config configuration file from the DiscoveryChat project.
  2. Add a new Service Behavior named DiscoveryBehavior inside the <serviceBehaviors> element.

    (Code Snippet – What is new in WCF4 Lab – serviceDiscovery config XML)

    App.config

    <behaviors>
    FakePre-a47c3cf58abb4ee39ecc86fcd146e82f-870ec55478124432843b8c3508d72dda <behavior name="DiscoveryBehavior"> <serviceDiscovery /> </behavior>FakePre-937554a38ac94508856a954a278467a5-902658a35682495f9dd42f29bd6c7553FakePre-53d8f004fc4149569b1fc1a2230a1b62-3b1741b9cdeb4b1da4adb957aea62950

  3. Modify the service description by adding the behaviorConfiguration attribute referencing the DiscoveryBehavior just created.

    App.config

    <services>
    FakePre-4c1c19ac34104921b88b119a7a75b3b5-0646822cb5c643c3b49e2d9ea8afe7c7 behaviorConfiguration="DiscoveryBehavior">FakePre-da9edc807f42456290ce02f0f81cfb95-1353038d01c943e18d5b40e066c12435FakePre-92a882e35fc9417b84881030da36fa61-79de71dec5be443abebe6d67b008d982FakePre-75052cc2529d41d7993595215641b9bc-89f8162585e2432b944583b402296ebbFakePre-600e6583c1db4c2c84eb255ec299a8c0-11182dc3fcc349d4bd97cbeebad280f2FakePre-ec643eb743c447c9a635d378a327b84f-b07ac9058667464cbd5246f4438cf6c9FakePre-6788608b724e4d5db482ca4d893d04d7-4a0d44a9fd9844bf955102f8c32749fb

  4. Next, you need to add a UDP discovery endpoint. This is where the discovery probe messages will be processed.

    Note:
    Probe Messages

    A Probe message is a WS-Discovery message used by a client to search for services on the network by service type. For more information about Probe messages, see section 5.2 of the WS-Discovery Specification.

    (Code Snippet - What is new in WCF4 Lab – udpDiscoveryEndpoint XML)

    App.config

    <services>
    FakePre-9ecba3acb8f041ac990434cd22d21cdd-ce06489440ac4c74ae174026df4ccdb2FakePre-81bae67e008a40c9a7e16b8267fd5aeb-852834390db94090913c406d555549fbFakePre-5f6dd1b9b02b469fb940f35d28595fe3-9510f214c5534b8a9ac91e5d7ab53a50FakePre-e637d62df34d47fe98f254000f629c11-3d907b82fcae428eaa2a4d0d4e626bb9FakePre-150570100a194d45b81a98aad31546a4-44ccce99876f4b028d7aba5abeae79c4FakePre-ee1c7cd033b74e7a8ef1dbbb6af56afb-8064f05c16ec4e5b884be5001cc60fbfFakePre-d843c38ac49746c5b61fed34cba718ff-79b2093c83c64cec934e328e05c43ee8 <endpoint name="udpDiscoveryEpt" kind="udpDiscoveryEndpoint"/>FakePre-f96c8a22e2bb413c9f3de8a6975324c9-2ed1493c389645228226d12592c24f83FakePre-096a189cecc44b48878ba7815ed1f285-6c8321088c134611ada0099bbf354da6FakePre-89b36c84f66f4534a35f2365ee29efd6-0d8d7a83b8a64cfbb6e58f14288deb14

    Note:
    Making Services Discoverable

    Adding the DiscoveryBehavior makes your service discoverable. The UDP endpoint (specified by the attribute kind = “udpDiscoveryEndpoint”) is where the discovery component will listen for discovery messages.

Task 2 – Enabling ad hoc Discovery

In this task, you will add code to asynchronously search for other chat users on the same subnet using service discovery. In order to utilize discovery functionality, you will need to add a reference to System.ServiceModel.Discovery to your project and add the associated namespace directive for System.ServiceModel.Discovery as well.

Note:
Note: This has already been done for you in the Begin solution for this Exercise.

  1. Open the SimpleChat form in code view by clicking on it, and pressing F7.
  2. Locate the AdHocDiscovery method stub and add the following code. This code will initiate discovery looking for services that implement the ISimpleChatService contract and then, as services are found, it will add them to the list of available services.

    (Code Snippet - What is new in WCF4 Lab – AdHocDiscovery Method CSharp)

    C#

    private void AdHocDiscovery()
    FakePre-4af2f792cb7a4e109c706d1dfa50ad44-391ab3797b114601b53c65a01172f7dc this.discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); this.discoveryClient.FindProgressChanged += new EventHandler<FindProgressChangedEventArgs>(this.OnFindProgressChanged); this.discoveryClient.FindCompleted += new EventHandler<FindCompletedEventArgs>(this.OnFindCompleted); // Setup the form for discovery this.ShowDiscoveryInProgress(true); // Do async discovery this.discoveryClient.FindAsync(new FindCriteria(typeof(ISimpleChatService)));FakePre-05189cfdb99542e2b51a55459b5c67a7-0258d6e10bab48afa971c7591d3fe770FakePre-cc2aa39818d04788977f2735f32f1ee4-3a82b1c80fe545c981db389da50fab9eFakePre-0cd02d15b9254034b3429f6d700d2f52-54c1da0497994bd5903aca14437771f9FakePre-e7388e1f0b754b30b46491ae3734aa96-984e17e02fbc4d5ebdda1d5d52f7a148

    (Code Snippet - What is new in WCF4 Lab – AdHocDiscovery Method VB)

    Visual Basic

    Private Sub AdHocDiscovery()
    Me._discoveryClient = New DiscoveryClient(New UdpDiscoveryEndpoint()) AddHandler _discoveryClient.FindProgressChanged, AddressOf OnFindProgressChanged AddHandler _discoveryClient.FindCompleted, AddressOf OnFindCompleted ' Setup the form for discovery Me.ShowDiscoveryInProgress(True) ' Do async discovery Me._discoveryClient.FindAsync(New FindCriteria(GetType(ISimpleChatService)))FakePre-aae310e2066544f5a4ecea480d402bdc-b634b8cc919c4555970e6a1a01224d9cFakePre-523eafa4113d447a8d19dedeb2af2d07-874579d3c56849d5be7bf91dbd42fb98FakePre-2dd880745beb4ff199de9f3bef00024d-0ac6fd255fc04cf78dcf04a453cda1c3FakePre-2b81491ac49c4adb85c82ca58cf898ce-b2ec320c32c84f89bce5612c65fac382FakePre-c5ed441b6d0b4fbaaa68ac3916229695-6298f018bea648bd842b4e6c1e81026f

    Note:
    Using DiscoveryClient

    The discovery process can be started either synchronous or asynchronously by using the Find or FindAsync methods respectively. Furthermore, you can also add a DynamicEndpoint to your application that searches performs discovery under the covers. In this application, you are using the FindAsync method because the asynchronous operation allows the chat peers to be added as they are discovered.

    During discovery, you can register some events handlers. For example, FindProgressChanged is invoked each time one of service endpoints has been discovered. If you want to be notified when the discovery process is finished, then the handler FindCompleted should be used.

  3. Implement the OnFindProgressChanged and OnFindCompleted handlers as shown in the following code by pasting it below the AdHocDiscovery() method implementation.

    (Code Snippet - What is new in WCF4 Lab – DiscoveryClient Event Handlers CSharp)

    C#

    private void OnFindProgressChanged(object sender, FindProgressChangedEventArgs e) { this.PopulateUserList(e.EndpointDiscoveryMetadata); } private void OnFindCompleted(object sender, FindCompletedEventArgs e) { if (e.Cancelled) { this.ShowStatus("Discovery cancelled"); } else if (e.Error != null) { this.discoveryClient.Close(); MessageBox.Show( e.Error.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, (MessageBoxOptions)0); } else { if (this.discoveryClient.InnerChannel.State == CommunicationState.Opened) { this.discoveryClient.Close(); } } this.discoveryClient = null; this.ShowDiscoveryInProgress(false); }
    FakePre-edfb563ce32a41e6afa226d814998b67-91ab9da9990d4b808288f14fba5de070
    

    (Code Snippet - What is new in WCF4 Lab – DiscoveryClient Event Handlers VB)

    Visual Basic

    Private Sub OnFindProgressChanged(ByVal sender As Object, ByVal e As FindProgressChangedEventArgs) Me.PopulateUserList(e.EndpointDiscoveryMetadata) End Sub Private Sub OnFindCompleted(ByVal sender As Object, ByVal e As FindCompletedEventArgs) If e.Cancelled Then Me.ShowStatus("Discovery cancelled") ElseIf e.Error IsNot Nothing Then Me._discoveryClient.Close() MessageBox.Show(e.Error.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, CType(0, MessageBoxOptions)) Else If Me._discoveryClient.InnerChannel.State = CommunicationState.Opened Then Me._discoveryClient.Close() End If End If Me._discoveryClient = Nothing Me.ShowDiscoveryInProgress(False) End Sub
    FakePre-fa5041271167410c9d08850d2df3fab9-4532d69ca6024b1c94b8636851bae81e
    

  4. Press CTRL+SHIFT+B to build the solution.

    Note:
    Watch Out

    DiscoveryChat will open an HTTP endpoint. If you try to do this without first creating a URL ACL, you will get an AddressAccessDeniedException.

    Figure 13

    AddressAccessDeniedException

  5. Create a URL ACL for port 8000. To do this

    1. Open a command prompt as administrator
    2. Run the SetUrlACL.cmd file from the Source\Setup folder as shown.

      CMD (Administrator)

      SetURLACL.cmd 8000

    Note:
    SetURLACL.cmd

    This script and the matching DelURLACL.cmd file are useful tools for managing URL ACLs.

Next Step

Exercise 4: Verification