Delen via


Communicatie in twee richtingen

Het voorbeeld in twee richtingen laat zien hoe u transacted tweerichtingscommunicatie uitvoert via MSMQ. In dit voorbeeld wordt de netMsmqBinding binding gebruikt. In dit geval is de service een zelf-hostende consoletoepassing waarmee u de service die berichten in de wachtrij ontvangt, kunt observeren.

Notitie

De installatieprocedure en build-instructies voor dit voorbeeld bevinden zich aan het einde van dit onderwerp.

Dit voorbeeld is gebaseerd op de Transacted MSMQ Binding.

Bij communicatie in de wachtrij communiceert de client met de service via een wachtrij. De client verzendt berichten naar een wachtrij en de service ontvangt berichten uit de wachtrij. De service en client hoeven daarom niet tegelijkertijd te worden uitgevoerd om te communiceren met behulp van een wachtrij.

In dit voorbeeld ziet u tweerichtingscommunicatie met behulp van wachtrijen. De client verzendt inkooporders naar de wachtrij binnen het bereik van een transactie. De service ontvangt de orders, verwerkt de order en roept vervolgens de client terug met de status van de order uit de wachtrij binnen het bereik van een transactie. Om communicatie in twee richtingen te vergemakkelijken, gebruiken de client en service wachtrijen om inkooporders en orderstatus in de wachtrij te plaatsen.

Het servicecontract IOrderProcessor definieert servicebewerkingen in één richting die passen bij het gebruik van wachtrijen. De servicebewerking bevat het antwoordeindpunt dat moet worden gebruikt om de orderstatussen naar te verzenden. Het antwoordeindpunt is de URI van de wachtrij om de orderstatus terug te sturen naar de client. De orderverwerkingstoepassing implementeert dit contract.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true)]
    void SubmitPurchaseOrder(PurchaseOrder po, string
                                  reportOrderStatusTo);
}

Het antwoordcontract voor het verzenden van de orderstatus wordt door de client opgegeven. De client implementeert het orderstatuscontract. De service gebruikt de gegenereerde proxy van dit contract om de orderstatus terug te sturen naar de client.

[ServiceContract]
public interface IOrderStatus
{
    [OperationContract(IsOneWay = true)]
    void OrderStatus(string poNumber, string status);
}

De servicebewerking verwerkt de ingediende inkooporder. De OperationBehaviorAttribute bewerking wordt toegepast op de servicebewerking om automatische opname in een transactie op te geven die wordt gebruikt voor het ontvangen van het bericht uit de wachtrij en automatische voltooiing van transacties na voltooiing van de servicebewerking. De Orders klasse bevat functionaliteit voor orderverwerking. In dit geval wordt de inkooporder toegevoegd aan een woordenlijst. De transactie waarin de servicebewerking is opgenomen, is beschikbaar voor de bewerkingen in de Orders klasse.

De servicebewerking, naast het verwerken van de ingediende inkooporder, reageert terug naar de client over de status van de order.

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
{
    Orders.Add(po);
    Console.WriteLine("Processing {0} ", po);
    Console.WriteLine("Sending back order status information");
    NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding("ClientCallbackBinding");
    OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));

    // Please note that the same transaction that is used to dequeue the purchase order is used
    // to send back order status.
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
    {
        client.OrderStatus(po.PONumber, po.Status);
        scope.Complete();
    }
    //Close the client.
    client.Close();
}

De naam van de MSMQ-wachtrij wordt opgegeven in een app Instellingen sectie van het configuratiebestand. Het eindpunt voor de service wordt gedefinieerd in de sectie System.ServiceModel van het configuratiebestand.

Notitie

De MSMQ-wachtrijnaam en het eindpuntadres gebruiken iets andere adresseringsconventies. De naam van de MSMQ-wachtrij maakt gebruik van een punt (.) voor de lokale computer en backslashscheidingstekens in het pad. Het WCF-eindpuntadres (Windows Communication Foundation) specificeert een net.msmq:-schema, gebruikt 'localhost' voor de lokale computer en maakt gebruik van slashes in het pad. Als u wilt lezen uit een wachtrij die wordt gehost op de externe computer, vervangt u de '' en 'localhost' in de naam van de externe computer.

De service wordt zelf gehost. Wanneer u het MSMQ-transport gebruikt, moet de gebruikte wachtrij vooraf worden gemaakt. Dit kan handmatig of via code. In dit voorbeeld controleert de service op het bestaan van de wachtrij en maakt deze, indien nodig. De naam van de wachtrij wordt gelezen uit het configuratiebestand. Het basisadres wordt gebruikt door het hulpprogramma ServiceModel Metadata Utility (Svcutil.exe) om de proxy voor de service te genereren.

// Host the service within this EXE console application.
public static void Main()
{
    // Get MSMQ queue name from appSettings in configuration.
    string queueName = ConfigurationManager.AppSettings["queueName"];

    // Create the transacted MSMQ queue if necessary.
    if (!MessageQueue.Exists(queueName))
        MessageQueue.Create(queueName, true);

    // Create a ServiceHost for the OrderProcessorService type.
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))
    {
        // Open the ServiceHost to create listeners and start listening for messages.
        serviceHost.Open();

        // The service can now be accessed.
        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.WriteLine();
        Console.ReadLine();
    }
}

De client maakt een transactie. Communicatie met de wachtrij vindt plaats binnen het bereik van de transactie, waardoor deze wordt behandeld als een atomische eenheid waarin alle berichten slagen of mislukken.

// Create a ServiceHost for the OrderStatus service type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{

    // Open the ServiceHostBase to create listeners and start listening for order status messages.
    serviceHost.Open();

    // Create the purchase order.
    ...

    // Create a client with given client endpoint configuration.
    OrderProcessorClient client = new OrderProcessorClient("OrderProcessorEndpoint");

    //Create a transaction scope.
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
    {
        string hostName = Dns.GetHostName();

        // Make a queued call to submit the purchase order.
        client.SubmitPurchaseOrder(po, "net.msmq://" + hostName + "/private/ServiceModelSamplesTwo-way/OrderStatus");

        // Complete the transaction.
        scope.Complete();
    }

    //Close down the client.
    client.Close();

    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to terminate client.");
    Console.ReadLine();

    // Close the ServiceHost to shutdown the service.
    serviceHost.Close();
}

De clientcode implementeert het IOrderStatus contract om de orderstatus van de service te ontvangen. In dit geval wordt de orderstatus afgedrukt.

[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
    [OperationBehavior(TransactionAutoComplete = true,
                        TransactionScopeRequired = true)]
    public void OrderStatus(string poNumber, string status)
    {
        Console.WriteLine("Status of order {0}:{1} ", poNumber ,
                                                           status);
    }
}

De orderstatuswachtrij wordt gemaakt in de Main methode. De clientconfiguratie bevat de configuratie van de orderstatusservice voor het hosten van de orderstatusservice, zoals wordt weergegeven in de volgende voorbeeldconfiguratie.

<appSettings>
  <!-- Use appSetting to configure MSMQ queue name. -->
  <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" />
</appSettings>

<system.serviceModel>

  <services>
    <service
       name="Microsoft.ServiceModel.Samples.OrderStatusService">
      <!-- Define NetMsmqEndpoint -->
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus"
                binding="netMsmqBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
    </service>
  </services>

  <client>
    <!-- Define NetMsmqEndpoint -->
    <endpoint name="OrderProcessorEndpoint"
              address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
              binding="netMsmqBinding"
              contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
  </client>

</system.serviceModel>

Wanneer u het voorbeeld uitvoert, worden de client- en serviceactiviteiten weergegeven in zowel de service- als clientconsolevensters. U ziet dat de service berichten van de client ontvangt. Druk in elk consolevenster op Enter om de service en client af te sluiten.

De service geeft de inkoopordergegevens weer en geeft aan dat deze de orderstatus terugstuurt naar de orderstatuswachtrij.

The service is ready.
Press <ENTER> to terminate service.

Processing Purchase Order: 124a1f69-3699-4b16-9bcc-43147a8756fc
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending

Sending back order status information

De client geeft de orderstatusgegevens weer die door de service worden verzonden.

Press <ENTER> to terminate client.
Status of order 124a1f69-3699-4b16-9bcc-43147a8756fc:Pending

Het voorbeeld instellen, compileren en uitvoeren

  1. Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.

  2. Als u de C# of Visual Basic .NET-editie van de oplossing wilt bouwen, volgt u de instructies in het bouwen van de Windows Communication Foundation-voorbeelden.

  3. Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Het uitvoeren van de Windows Communication Foundation-voorbeelden.

    Notitie

    Als u Svcutil.exe gebruikt om de configuratie voor dit voorbeeld opnieuw te genereren, moet u de eindpuntnamen in de clientconfiguratie wijzigen zodat deze overeenkomen met de clientcode.

NetMsmqBindingStandaard is transportbeveiliging ingeschakeld. Er zijn twee relevante eigenschappen voor MSMQ-transportbeveiliging. MsmqProtectionLevelMsmqAuthenticationMode. De verificatiemodus is standaard ingesteld op Windows en het beveiligingsniveau is ingesteld op.Sign MsMQ moet deel uitmaken van een domein en moet de active directory-integratieoptie voor MSMQ zijn geïnstalleerd om de verificatie- en ondertekeningsfunctie op te geven. Als u dit voorbeeld uitvoert op een computer die niet aan deze criteria voldoet, krijgt u een foutmelding.

Het voorbeeld uitvoeren op een computer die is gekoppeld aan een werkgroep of zonder Active Directory-integratie

  1. Als uw computer geen deel uitmaakt van een domein of geen Active Directory-integratie heeft geïnstalleerd, schakelt u transportbeveiliging uit door de verificatiemodus en het beveiligingsniveau in te None stellen op zoals wordt weergegeven in de volgende voorbeeldconfiguratie:

    <configuration>
    
      <appSettings>
        <!-- Use appSetting to configure MSMQ queue name. -->
        <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderProcessor" />
      </appSettings>
    
      <system.serviceModel>
        <services>
          <service
              name="Microsoft.ServiceModel.Samples.OrderProcessorService">
            <!-- Define NetMsmqEndpoint -->
            <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
                      binding="netMsmqBinding"
                      bindingConfiguration="TransactedBinding"
                      contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
          </service>
        </services>
    
        <bindings>
          <netMsmqBinding>
            <binding name="TransactedBinding" >
             <security mode="None" />
            </binding>
          </netMsmqBinding>
        </bindings>
    
      </system.serviceModel>
    
    </configuration>
    
  2. Als u de beveiliging voor een clientconfiguratie uitschakelt, wordt het volgende gegenereerd:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <!-- Use appSetting to configure MSMQ queue name. -->
        <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" />
      </appSettings>
    
      <system.serviceModel>
    
        <services>
          <service
             name="Microsoft.ServiceModel.Samples.OrderStatusService">
            <!-- Define NetMsmqEndpoint -->
            <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus"
                      binding="netMsmqBinding"
                      bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
          </service>
        </services>
    
        <client>
          <!-- Define NetMsmqEndpoint -->
          <endpoint name="OrderProcessorEndpoint"
                    address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
                    binding="netMsmqBinding"
                    bindingConfiguration="TransactedBinding"
                    contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
        </client>
    
        <bindings>
          <netMsmqBinding>
            <binding name="TransactedBinding" >
             <security mode="None" />
            </binding>
          </netMsmqBinding>
        </bindings>
    
      </system.serviceModel>
    
    </configuration>
    
  3. De service voor dit voorbeeld maakt een binding in de OrderProcessorService. Voeg een coderegel toe nadat de binding is geïnstantieerd om de beveiligingsmodus in te stellen op None.

    NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
    msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;
    
  4. Zorg ervoor dat u de configuratie op zowel de server als de client wijzigt voordat u het voorbeeld uitvoert.

    Notitie

    Instelling security mode is None gelijk aan MsmqAuthenticationModeinstelling of MsmqProtectionLevelMessage beveiliging op None.