Udostępnij za pośrednictwem


Transport: UDP

W przykładzie UDP Transport pokazano, jak zaimplementować emisję uniemisji UDP i multiemisji jako niestandardowy transport programu Windows Communication Foundation (WCF). W przykładzie opisano zalecaną procedurę tworzenia transportu niestandardowego w programie WCF przy użyciu platformy kanału i zgodnie z najlepszymi rozwiązaniami dotyczącymi programu WCF. Kroki tworzenia transportu niestandardowego są następujące:

  1. Zdecyduj, które wzorce wymiany komunikatów kanału (IOutputChannel, IInputChannel, IDuplexChannel, IRequestChannel lub IReplyChannel) będą obsługiwane przez element ChannelFactory i ChannelListener. Następnie zdecyduj, czy będziesz obsługiwać sesjowe odmiany tych interfejsów.

  2. Utwórz fabrykę kanałów i odbiornik obsługujący wzorzec wymiany komunikatów.

  3. Upewnij się, że wszystkie wyjątki specyficzne dla sieci są znormalizowane do odpowiedniej klasy pochodnej klasy CommunicationException.

  4. <Dodaj element powiązania>, który dodaje niestandardowy transport do stosu kanału. Aby uzyskać więcej informacji, zobacz Dodawanie elementu powiązania.

  5. Dodaj sekcję rozszerzenia elementu powiązania, aby uwidocznić nowy element powiązania w systemie konfiguracji.

  6. Dodaj rozszerzenia metadanych, aby komunikować się z innymi punktami końcowymi.

  7. Dodaj powiązanie, które wstępnie konfiguruje stos elementów powiązania zgodnie z dobrze zdefiniowanym profilem. Aby uzyskać więcej informacji, zobacz Dodawanie powiązania standardowego.

  8. Dodaj sekcję powiązania i element konfiguracji powiązania, aby uwidocznić powiązanie z systemem konfiguracji. Aby uzyskać więcej informacji, zobacz Dodawanie obsługi konfiguracji.

Wzorce wymiany komunikatów

Pierwszym krokiem w pisaniu transportu niestandardowego jest podjęcie decyzji, które wzorce wymiany komunikatów (MEPs) są wymagane do transportu. Spośród trzech posłów do PE należy wybrać:

  • Datagram (IInputChannel/IOutputChannel)

    W przypadku korzystania z datagramu MEP klient wysyła komunikat przy użyciu wymiany "fire and forget". Ogień i zapominanie wymiany jest taki, który wymaga potwierdzenia poza pasmem pomyślnego dostarczenia. Wiadomość może zostać utracona podczas przesyłania i nigdy nie dociera do usługi. Jeśli operacja wysyłania zakończy się pomyślnie na końcu klienta, nie gwarantuje, że zdalny punkt końcowy odebrał komunikat. Datagram jest podstawowym blokiem konstrukcyjnym do obsługi komunikatów, ponieważ można tworzyć własne protokoły, w tym niezawodne protokoły i bezpieczne protokoły. Kanały datagramu klienta implementują IOutputChannel interfejs i kanały datagramu usługi implementują IInputChannel interfejs.

  • Request-Response (IRequestChannel/IReplyChannel)

    W tym mepcie zostanie wysłana wiadomość i otrzymana jest odpowiedź. Wzorzec składa się z par żądań-odpowiedzi. Przykłady wywołań żądań odpowiedzi to zdalne wywołania procedur (RPC) i gets przeglądarki. Ten wzorzec jest również znany jako Half-Duplex. W tym mepcie kanały klienta implementują IRequestChannel i implementują IReplyChannelkanały usług .

  • Duplex (IDuplexChannel)

    Dupleksowy poseł DO PE umożliwia dowolną liczbę komunikatów wysyłanych przez klienta i odbieranych w dowolnej kolejności. Dwudupleksowy poseł do PE jest jak rozmowa telefoniczna, gdzie każde słowo mówione jest wiadomością. Ponieważ obie strony mogą wysyłać i odbierać w tym mepcie, interfejs implementowany przez klienta i kanały usług to IDuplexChannel.

Każdy z tych posłów może również wspierać sesje. Dodatkową funkcją zapewnianą przez kanał obsługujący sesję jest skorelowanie wszystkich komunikatów wysłanych i odebranych w kanale. Wzorzec żądanie-odpowiedź jest autonomiczną sesją z dwoma komunikatami, ponieważ żądanie i odpowiedź są skorelowane. Z kolei wzorzec request-response obsługujący sesje oznacza, że wszystkie pary żądań/odpowiedzi w tym kanale są skorelowane ze sobą. Zapewnia to łącznie sześć posłów do pe— Datagram, Request-Response, Duplex, Datagram z sesjami, Request-Response z sesjami i Dupleks z sesjami — do wyboru.

Uwaga

W przypadku transportu UDP jedynym obsługiwanym deputowanym jest Datagram, ponieważ UDP jest z natury protokołem "fire and forget".

ICommunicationObject i cykl życia obiektu WCF

WCF ma typową maszynę stanu, która służy do zarządzania cyklem życia obiektów, takich jak IChannel, IChannelFactoryi IChannelListener , które są używane do komunikacji. Istnieje pięć stanów, w których te obiekty komunikacyjne mogą istnieć. Te stany są reprezentowane przez CommunicationState wyliczenie i są następujące:

  • Utworzone: jest to stan ICommunicationObject pierwszego wystąpienia. W tym stanie nie ma danych wejściowych/wyjściowych (we/wy).

  • Otwieranie: obiekty przechodzą do tego stanu, gdy Open jest wywoływany. W tym momencie właściwości są niezmienne, a dane wejściowe/wyjściowe mogą się rozpocząć. To przejście jest prawidłowe tylko ze stanu Utworzone.

  • Otwarte: obiekty przechodzą do tego stanu po zakończeniu procesu otwierania. To przejście jest prawidłowe tylko ze stanu Otwarcie. W tym momencie obiekt jest w pełni użyteczny do transferu.

  • Zamykanie: Obiekty przechodzą do tego stanu, gdy Close jest wywoływany w celu bezpiecznego zamknięcia. To przejście jest prawidłowe tylko ze stanu Otwarte.

  • Zamknięte: W obiektach stanu Zamknięte nie można już używać. Ogólnie rzecz biorąc, większość konfiguracji jest nadal dostępna do inspekcji, ale nie może wystąpić żadna komunikacja. Ten stan jest odpowiednikiem usuwania.

  • Uszkodzony: w stanie Uszkodzony obiekty są dostępne do inspekcji, ale nie są już używane. Gdy wystąpi błąd niemożliwy do odzyskania, obiekt przechodzi do tego stanu. Jedynym prawidłowym przejściem z tego stanu jest przejście do Closed stanu.

Istnieją zdarzenia uruchamiane dla każdego przejścia stanu. Metoda Abort może być wywoływana w dowolnym momencie i powoduje natychmiastowe przejście obiektu z bieżącego stanu do stanu Zamknięte. Wywołanie Abort kończy pracę niedokończoną.

Fabryka kanałów i odbiornik kanału

Następnym krokiem w pisaniu transportu niestandardowego jest utworzenie implementacji IChannelFactory kanałów klienta i kanałów IChannelListener usług. Warstwa kanału używa wzorca fabryki do konstruowania kanałów. Program WCF udostępnia pomocników klasy bazowej dla tego procesu.

W tym przykładzie implementacja fabryki jest zawarta w UdpChannelFactory.cs, a implementacja odbiornika jest zawarta w UdpChannelListener.cs. Implementacje IChannel są w UdpOutputChannel.cs i UdpInputChannel.cs.

Fabryka kanałów UDP

Element UdpChannelFactory pochodzi z klasy ChannelFactoryBase. Przykładowe GetProperty zastąpienia w celu zapewnienia dostępu do wersji komunikatu kodera komunikatów. Przykład zastępuje OnClose również to, abyśmy mogli usunąć nasze wystąpienie BufferManager , gdy maszyna stanu przechodzi.

Kanał wyjściowy UDP

Implementuje element UdpOutputChannelIOutputChannel. Konstruktor weryfikuje argumenty i konstruuje obiekt docelowy EndPoint na podstawie przekazanego EndpointAddress obiektu.

this.socket = new Socket(this.remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

Kanał można zamknąć z wdziękiem lub niegrzecznie. Jeśli kanał jest zamknięty bezpiecznie, gniazdo jest zamknięte i wywołanie jest wykonywane do metody klasy OnClose bazowej. Jeśli zgłosi to wyjątek, wywołania Abort infrastruktury w celu upewnienia się, że kanał zostanie oczyszczony.

this.socket.Close(0);

Następnie implementujemy Send() i BeginSend()/EndSend(). Jest to podzielone na dwie główne sekcje. Najpierw serializujemy komunikat w tablicy bajtów.

ArraySegment<byte> messageBuffer = EncodeMessage(message);

Następnie wysyłamy wynikowe dane na przewodach.

this.socket.SendTo(messageBuffer.Array, messageBuffer.Offset, messageBuffer.Count, SocketFlags.None, this.remoteEndPoint);

Element UdpChannelListener

Przykład UdpChannelListener implementuje pochodną ChannelListenerBase klasy . Używa pojedynczego gniazda UDP do odbierania datagramów. Metoda OnOpen odbiera dane przy użyciu gniazda UDP w pętli asynchronicznej. Dane są następnie konwertowane na komunikaty przy użyciu struktury kodowania komunikatów.

message = MessageEncoderFactory.Encoder.ReadMessage(new ArraySegment<byte>(buffer, 0, count), bufferManager);

Ponieważ ten sam kanał datagramu reprezentuje komunikaty pochodzące z wielu źródeł, UdpChannelListener jest to pojedynczy odbiornik. Istnieje co najwyżej jedna aktywna IChannel skojarzona z tym odbiornikiem jednocześnie. Przykład generuje inny tylko wtedy, gdy kanał zwracany przez metodę AcceptChannel jest następnie usuwany. Po odebraniu komunikatu jest on umieszczany w kolejce do tego kanału pojedynczego.

UdpInputChannel

Klasa UdpInputChannel implementuje IInputChannelelement . Składa się z kolejki komunikatów przychodzących wypełnianych przez UdpChannelListenergniazdo . Te komunikaty są dequeued przez metodę IInputChannel.Receive .

Dodawanie elementu powiązania

Teraz, gdy fabryki i kanały zostały skompilowane, musimy udostępnić je środowisku uruchomieniowemu modelu ServiceModel za pomocą powiązania. Powiązanie to kolekcja elementów powiązania, które reprezentują stos komunikacji skojarzony z adresem usługi. Każdy element w stosie jest reprezentowany przez element powiązania>.<

W przykładzie element powiązania to UdpTransportBindingElement, który pochodzi z elementu TransportBindingElement. Zastępuje następujące metody tworzenia fabryk skojarzonych z naszym powiązaniem.

public IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
    return (IChannelFactory<TChannel>)(object)new UdpChannelFactory(this, context);
}

public IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
    return (IChannelListener<TChannel>)(object)new UdpChannelListener(this, context);
}

Zawiera również elementy członkowskie do klonowania i zwracania naszego schematu BindingElement (soap.udp).

Dodawanie obsługi metadanych dla elementu powiązania transportu

Aby zintegrować nasz transport z systemem metadanych, musimy obsługiwać zarówno importowanie, jak i eksportowanie zasad. Dzięki temu możemy wygenerować klientów naszego powiązania za pomocą narzędzia ServiceModel Metadata Tool (Svcutil.exe).

Dodawanie obsługi języka WSDL

Element powiązania transportu w powiązaniu jest odpowiedzialny za eksportowanie i importowanie informacji dotyczących adresowania w metadanych. W przypadku korzystania z powiązania protokołu SOAP element powiązania transportu powinien również wyeksportować prawidłowy identyfikator URI transportu w metadanych.

Eksportowanie WSDL

Aby wyeksportować informacje dotyczące adresowania, UdpTransportBindingElement implementuje IWsdlExportExtension interfejs. Metoda ExportEndpoint dodaje poprawne informacje adresowania do portu WSDL.

if (context.WsdlPort != null)
{
    AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);
}

Implementacja UdpTransportBindingElementExportEndpoint metody eksportuje również identyfikator URI transportu, gdy punkt końcowy używa powiązania protokołu SOAP.

WsdlNS.SoapBinding soapBinding = GetSoapBinding(context, exporter);
if (soapBinding != null)
{
    soapBinding.Transport = UdpPolicyStrings.UdpNamespace;
}

Importowanie WSDL

Aby rozszerzyć system importu WSDL w celu obsługi importowania adresów, musimy dodać następującą konfigurację do pliku konfiguracji dla Svcutil.exe, jak pokazano w pliku Svcutil.exe.config.

<configuration>
  <system.serviceModel>
    <client>
      <metadata>
        <policyImporters>
          <extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
        </policyImporters>
      </metadata>
    </client>
  </system.serviceModel>
</configuration>

W przypadku uruchamiania Svcutil.exe istnieją dwie opcje pobierania Svcutil.exe ładowania rozszerzeń importu WSDL:

  1. Wskaż Svcutil.exe do pliku konfiguracji przy użyciu pliku /SvcutilConfig:<file>.

  2. Dodaj sekcję konfiguracji do pliku Svcutil.exe.config w tym samym katalogu co Svcutil.exe.

Typ UdpBindingElementImporter implementuje IWsdlImportExtension interfejs. Metoda ImportEndpoint importuje adres z portu WSDL.

BindingElementCollection bindingElements = context.Endpoint.Binding.CreateBindingElements();
TransportBindingElement transportBindingElement = bindingElements.Find<TransportBindingElement>();
if (transportBindingElement is UdpTransportBindingElement)
{
    ImportAddress(context);
}

Dodawanie obsługi zasad

Niestandardowy element powiązania może eksportować asercji zasad w powiązaniu WSDL dla punktu końcowego usługi, aby wyrazić możliwości tego elementu powiązania.

Eksportowanie zasad

Typ UdpTransportBindingElement implementuje IPolicyExportExtension obsługę eksportowania zasad. W związku z tym System.ServiceModel.MetadataExporter uwzględnia UdpTransportBindingElement generowanie zasad dla wszystkich powiązań, które go zawierają.

W IPolicyExportExtension.ExportPolicysystemie dodamy asercji dla protokołu UDP i inną asercję, jeśli jesteśmy w trybie multiemisji. Wynika to z faktu, że tryb multiemisji wpływa na sposób konstruowania stosu komunikacyjnego, a tym samym musi być skoordynowany między obie strony.

ICollection<XmlElement> bindingAssertions = context.GetBindingAssertions();
XmlDocument xmlDocument = new XmlDocument();
bindingAssertions.Add(xmlDocument.CreateElement(
UdpPolicyStrings.Prefix, UdpPolicyStrings.TransportAssertion, UdpPolicyStrings.UdpNamespace));
if (Multicast)
{
    bindingAssertions.Add(xmlDocument.CreateElement(
        UdpPolicyStrings.Prefix,
        UdpPolicyStrings.MulticastAssertion,
        UdpPolicyStrings.UdpNamespace));
}

Ponieważ niestandardowe elementy powiązania transportu są odpowiedzialne za obsługę adresowania, IPolicyExportExtension implementacja obiektu UdpTransportBindingElement musi również obsługiwać eksportowanie odpowiednich asercji zasad adresowania WS, aby wskazać wersję używanej wersji adresowania WS.

AddWSAddressingAssertion(context, encodingBindingElement.MessageVersion.Addressing);

Importowanie zasad

Aby rozszerzyć system importu zasad, musimy dodać następującą konfigurację do pliku konfiguracji dla Svcutil.exe, jak pokazano w pliku Svcutil.exe.config.

<configuration>
  <system.serviceModel>
    <client>
      <metadata>
        <policyImporters>
          <extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
        </policyImporters>
      </metadata>
    </client>
  </system.serviceModel>
</configuration>

Następnie implementujemy IPolicyImporterExtension z naszej zarejestrowanej klasy (UdpBindingElementImporter). W ImportPolicy()systemie przejrzymy asercji w naszej przestrzeni nazw i przetwarzamy te do generowania transportu i sprawdzamy, czy jest multiemisji. Musimy również usunąć asercji, które obsługujemy z listy asercji powiązań. Ponownie podczas uruchamiania Svcutil.exe istnieją dwie opcje integracji:

  1. Wskaż Svcutil.exe do pliku konfiguracji przy użyciu pliku /SvcutilConfig:<file>.

  2. Dodaj sekcję konfiguracji do pliku Svcutil.exe.config w tym samym katalogu co Svcutil.exe.

Dodawanie powiązania standardowego

Nasz element powiązania może być używany na następujące dwa sposoby:

  • Za pomocą powiązania niestandardowego: powiązanie niestandardowe umożliwia użytkownikowi tworzenie własnego powiązania na podstawie dowolnego zestawu elementów powiązania.

  • Za pomocą powiązania dostarczonego przez system, które zawiera nasz element powiązania. Program WCF udostępnia szereg tych powiązań zdefiniowanych przez system, takich jak BasicHttpBinding, NetTcpBindingi WsHttpBinding. Każde z tych powiązań jest skojarzone z dobrze zdefiniowanym profilem.

Przykład implementuje powiązanie profilu w elemecie SampleProfileUdpBinding, które pochodzi z elementu Binding. Element SampleProfileUdpBinding zawiera maksymalnie cztery elementy powiązania: UdpTransportBindingElement, TextMessageEncodingBindingElement CompositeDuplexBindingElementi ReliableSessionBindingElement.

public override BindingElementCollection CreateBindingElements()
{
    BindingElementCollection bindingElements = new BindingElementCollection();
    if (ReliableSessionEnabled)
    {
        bindingElements.Add(session);
        bindingElements.Add(compositeDuplex);
    }
    bindingElements.Add(encoding);
    bindingElements.Add(transport);
    return bindingElements.Clone();
}

Dodawanie niestandardowego importera powiązań standardowych

Svcutil.exe i WsdlImporter typ, domyślnie rozpoznaje i importuje powiązania zdefiniowane przez system. W przeciwnym razie powiązanie zostanie zaimportowane jako CustomBinding wystąpienie. Aby umożliwić Svcutil.exe i WsdlImporter import, SampleProfileUdpBindingUdpBindingElementImporter również działa jako niestandardowy importer powiązania standardowego.

Niestandardowy importer powiązania standardowego implementuje ImportEndpoint metodę w interfejsie IWsdlImportExtension w celu sprawdzenia CustomBinding wystąpienia zaimportowanego z metadanych w celu sprawdzenia, czy mogło zostać wygenerowane przez określone powiązanie standardowe.

if (context.Endpoint.Binding is CustomBinding)
{
    Binding binding;
    if (transportBindingElement is UdpTransportBindingElement)
    {
        //if TryCreate is true, the CustomBinding will be replace by a SampleProfileUdpBinding in the
        //generated config file for better typed generation.
        if (SampleProfileUdpBinding.TryCreate(bindingElements, out binding))
        {
            binding.Name = context.Endpoint.Binding.Name;
            binding.Namespace = context.Endpoint.Binding.Namespace;
            context.Endpoint.Binding = binding;
        }
    }
}

Ogólnie rzecz biorąc, implementacja niestandardowego importera powiązania standardowego polega na sprawdzeniu właściwości importowanych elementów powiązania w celu sprawdzenia, czy tylko właściwości, które mogły zostać ustawione przez powiązanie standardowe, uległy zmianie, a wszystkie inne właściwości są ich wartościami domyślnymi. Podstawową strategią implementacji standardowego importera powiązania jest utworzenie wystąpienia powiązania standardowego, propagowanie właściwości z elementów powiązania standardowego do standardowego wystąpienia powiązania obsługiwanego przez powiązanie standardowe oraz porównanie elementów powiązania standardowego z importowanymi elementami powiązania.

Dodawanie obsługi konfiguracji

Aby uwidocznić nasz transport za pośrednictwem konfiguracji, musimy zaimplementować dwie sekcje konfiguracji. Pierwszy to element BindingElementExtensionElement dla UdpTransportBindingElementelementu . Dzięki temu CustomBinding implementacje mogą odwoływać się do naszego elementu powiązania. Drugi jest elementem Configuration dla naszego SampleProfileUdpBindingelementu .

Binding, element extension, element

Sekcja UdpTransportElement jest elementem uwidacznianym BindingElementExtensionElementUdpTransportBindingElement w systemie konfiguracji. Za pomocą kilku podstawowych przesłonięć definiujemy nazwę sekcji konfiguracji, typ naszego elementu powiązania i sposób tworzenia naszego elementu powiązania. Następnie możemy zarejestrować naszą sekcję rozszerzenia w pliku konfiguracji, jak pokazano w poniższym kodzie.

<configuration>
  <system.serviceModel>
    <extensions>
      <bindingElementExtensions>
        <add name="udpTransport" type="Microsoft.ServiceModel.Samples.UdpTransportElement, UdpTransport" />
      </bindingElementExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

Do rozszerzenia można odwoływać się z powiązań niestandardowych, aby używać protokołu UDP jako transportu.

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
       <binding configurationName="UdpCustomBinding">
         <udpTransport/>
       </binding>
      </customBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Sekcja powiązania

Sekcja SampleProfileUdpBindingCollectionElement jest elementem uwidacznianym StandardBindingCollectionElementSampleProfileUdpBinding w systemie konfiguracji. Większość implementacji jest delegowana do SampleProfileUdpBindingConfigurationElementklasy , która pochodzi z klasy StandardBindingElement. Zawiera SampleProfileUdpBindingConfigurationElement właściwości, które odpowiadają właściwościom elementu SampleProfileUdpBindingi funkcji do mapowania z ConfigurationElement powiązania. Na koniec przesłoń metodę OnApplyConfiguration w pliku SampleProfileUdpBinding, jak pokazano w poniższym przykładowym kodzie.

protected override void OnApplyConfiguration(string configurationName)
{
    if (binding == null)
        throw new ArgumentNullException("binding");

    if (binding.GetType() != typeof(SampleProfileUdpBinding))
    {
        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
            "Invalid type for binding. Expected type: {0}. Type passed in: {1}.",
            typeof(SampleProfileUdpBinding).AssemblyQualifiedName,
            binding.GetType().AssemblyQualifiedName));
    }
    SampleProfileUdpBinding udpBinding = (SampleProfileUdpBinding)binding;

    udpBinding.OrderedSession = this.OrderedSession;
    udpBinding.ReliableSessionEnabled = this.ReliableSessionEnabled;
    udpBinding.SessionInactivityTimeout = this.SessionInactivityTimeout;
    if (this.ClientBaseAddress != null)
        udpBinding.ClientBaseAddress = ClientBaseAddress;
}

Aby zarejestrować tę procedurę obsługi w systemie konfiguracji, dodamy następującą sekcję do odpowiedniego pliku konfiguracji.

<configuration>
  <configSections>
     <sectionGroup name="system.serviceModel">
        <sectionGroup name="bindings">
          <section name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />
        </sectionGroup>
     </sectionGroup>
  </configSections>
</configuration>

Następnie można się do niego odwołać w sekcji konfiguracji serviceModel.

<configuration>
  <system.serviceModel>
    <client>
      <endpoint configurationName="calculator"
                address="soap.udp://localhost:8001/"
                bindingConfiguration="CalculatorServer"
                binding="sampleProfileUdpBinding"
                contract= "Microsoft.ServiceModel.Samples.ICalculatorContract">
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

Usługa testowa UDP i klient

Kod testowy do korzystania z tego przykładowego transportu jest dostępny w katalogach UdpTestService i UdpTestClient. Kod usługi składa się z dwóch testów — jeden test konfiguruje powiązania i punkty końcowe z kodu, a drugi przez konfigurację. Oba testy używają dwóch punktów końcowych. Jeden punkt końcowy używa parametru SampleUdpProfileBinding z parametrem <reliableSession> ustawionym na truewartość . Drugi punkt końcowy używa niestandardowego powiązania z elementem UdpTransportBindingElement. Jest to równoważne użyciu SampleUdpProfileBinding z elementem <reliableSession> ustawionym na falsewartość . Oba testy tworzą usługę, dodaj punkt końcowy dla każdego powiązania, otwórz usługę, a następnie poczekaj, aż użytkownik trafi do klawisza ENTER przed zamknięciem usługi.

Po uruchomieniu aplikacji testowej usługi powinny zostać wyświetlone następujące dane wyjściowe.

Testing Udp From Code.
Service is started from code...
Press <ENTER> to terminate the service and start service from config...

Następnie można uruchomić testowej aplikacji klienckiej względem opublikowanych punktów końcowych. Aplikacja testowa klienta tworzy klienta dla każdego punktu końcowego i wysyła pięć komunikatów do każdego punktu końcowego. Następujące dane wyjściowe są na kliencie.

Testing Udp From Imported Files Generated By SvcUtil.
0
3
6
9
12
Press <ENTER> to complete test.

Poniżej przedstawiono pełne dane wyjściowe usługi.

Service is started from code...
Press <ENTER> to terminate the service and start service from config...
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
   adding 0 + 0
   adding 1 + 2
   adding 2 + 4
   adding 3 + 6
   adding 4 + 8

Aby uruchomić aplikację kliencją względem punktów końcowych opublikowanych przy użyciu konfiguracji, naciśnij klawisz ENTER w usłudze, a następnie ponownie uruchom klienta testowego. W usłudze powinny zostać wyświetlone następujące dane wyjściowe.

Testing Udp From Config.
Service is started from config...
Press <ENTER> to terminate the service and exit...

Ponowne uruchomienie klienta daje takie same wyniki jak poprzednie wyniki.

Aby ponownie wygenerować kod klienta i konfigurację przy użyciu Svcutil.exe, uruchom aplikację usługi, a następnie uruchom następujące Svcutil.exe z katalogu głównego przykładu.

svcutil http://localhost:8000/udpsample/ /reference:UdpTransport\bin\UdpTransport.dll /svcutilConfig:svcutil.exe.config

Należy pamiętać, że Svcutil.exe nie generuje konfiguracji rozszerzenia powiązania dla SampleProfileUdpBindingelementu , dlatego należy dodać ją ręcznie.

<configuration>
  <system.serviceModel>
    <extensions>
      <!-- This was added manually because svcutil.exe does not add this extension to the file -->
      <bindingExtensions>
        <add name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />
      </bindingExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

Aby skonfigurować, skompilować i uruchomić przykład

  1. Aby skompilować rozwiązanie, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).

  2. Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.

  3. Zapoznaj się z poprzednią sekcją "Usługa testowa UDP i klient".