Udostępnij przez


Transmisja: UDP

W przykładzie UDP Transport pokazano, jak zaimplementować unicast i multicast dla UDP jako niestandardowy transport w ramach Windows Communication Foundation (WCF). W tym przykładzie opisano zalecaną procedurę tworzenia transportu niestandardowego w programie WCF przy użyciu frameworku kanałów i zgodnie z najlepszymi praktykami 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 nasłuchiwacz 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 udostępnić powiązanie systemowi 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 "wyślij i zapomnij". Transakcja „wystrzel i zapomnij” to taka, która wymaga potwierdzenia poza kanałem, że dostarczenie było pomyślne. 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 po stronie klienta, nie gwarantuje, że zdalny odbiorca 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 MEP wysyła się wiadomość, a odpowiedź jest otrzymywana. Wzorzec składa się z par żądań-odpowiedzi. Przykłady wywołań typu żądanie-odpowiedź to zdalne wywołania procedur (RPC) i metody GET przeglądarki. Ten wzorzec jest również znany jako Half-Duplex. W tym MEP kanały klienta implementują IRequestChannel, a kanały usług implementują IReplyChannel.

  • Duplex (IDuplexChannel)

    Dupleksowy wzorzec wymiany wiadomości umożliwia przesyłanie przez klienta dowolnej liczby komunikatów i odbieranie ich w dowolnej kolejności. Dwudupleksowy poseł do PE jest jak rozmowa telefoniczna, gdzie każde słowo mówione jest wiadomością. Ponieważ w tym MEP obie strony mogą zarówno wysyłać, jak i odbierać, interfejs implementowany przez klienta oraz kanały usług jest 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 Request-Response jest samodzielną 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ą. Daje 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 / Notatka

Dla transportu UDP jedynym obsługiwanym wzorcem wymiany komunikatów (MEP) jest Datagram, ponieważ UDP jest z natury protokołem "wystrzel i zapomnij".

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ą przedstawiane przez enumerację CommunicationState i prezentują się następująco:

  • Utworzone: To jest stan ICommunicationObject po jego pierwszym zainicjowaniu. W tym stanie nie zachodzi wejście/wyjście (I/O).

  • Otwieranie: obiekty przechodzą do tego stanu, gdy Open jest wywoływany. W tym momencie właściwości zostają uczynione niezmiennymi, a operacje wejścia/wyjścia 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 Otwartego.

  • Zamknięte: W stanie Zamknięte obiekty nie są już używane. 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 równoważny z byciem odrzuconym.

  • 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 dla kanałów klienta i IChannelListener dla kanałów 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 nasłuchiwacza jest zawarta w UdpChannelListener.cs. Implementacje IChannel są w UdpOutputChannel.cs i UdpInputChannel.cs.

Fabryka kanałów UDP

UdpChannelFactory pochodzi z ChannelFactoryBase. Przykład nadpisuje GetProperty, aby zapewnić dostęp do wersji komunikatu dekodera. Przykład również zastępuje OnClose po to, abyśmy mogli usunąć nasze wystąpienie BufferManager w momencie przejścia maszyny stanowej.

Kanał wyjściowy UDP

Element UdpOutputChannel implementuje IOutputChannel. 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, infrastruktura wywołuje Abort 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 do sieci.

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

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.

Kanał Wejściowy UDP

Klasa UdpInputChannel implementuje IInputChannel. Składa się z kolejki komunikatów przychodzących, którą wypełnia gniazdo UdpChannelListener. Te komunikaty są usuwane z kolejki przez metodę IInputChannel.Receive.

Dodawanie elementu powiązania

Teraz, gdy fabryki i kanały zostały zbudowane, musimy wyeksponować je środowisku wykonawczemu 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ż członków do klonowania BindingElement i zwracania naszego schematu (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 wiązania transportowego 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 wyeksportować w metadanych również prawidłowy identyfikator URI transportu.

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 UdpTransportBindingElement metody ExportEndpoint eksportuje identyfikator URI transportu również wtedy, 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 do 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>

Podczas uruchamiania Svcutil.exeistnieją dwie opcje, aby Svcutil.exe mogło załadować rozszerzenia importu WSDL:

  1. Wskaż Svcutil.exe na nasz plik konfiguracyjny, używając parametru /SvcutilConfig:<file>.

  2. Dodaj sekcję konfiguracji do 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 wsparcia dla polityki

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

Eksport zasad

Typ UdpTransportBindingElement implementuje IPolicyExportExtension w celu dodania obsługi eksportu zasad. W związku z tym System.ServiceModel.MetadataExporter uwzględnia UdpTransportBindingElement w generowaniu polityk dla wszystkich powiązań, które je zawierają.

W IPolicyExportExtension.ExportPolicy dodajemy asercję 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 WS-Addressing w celu wskazania wersji używanej WS-Addressing.

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() przeglądamy asercje w naszej przestrzeni nazw i przetwarzamy te, które są przeznaczone do generowania transportu, sprawdzając, czy jest multicastem. Musimy również usunąć asercje, które obsługujemy, z listy wiążących asercji. Ponownie podczas uruchamiania Svcutil.exeistnieją dwie opcje integracji:

  1. Wskaż Svcutil.exe na nasz plik konfiguracyjny, używając parametru /SvcutilConfig:<file>.

  2. Dodaj sekcję konfiguracji do 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 obiekcie SampleProfileUdpBinding, który wywodzi się z obiektu 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 definowanego 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 wystąpienie CustomBinding. Aby umożliwić import Svcutil.exe i WsdlImporter, SampleProfileUdpBindingUdpBindingElementImporter również działa jako niestandardowy importer standardowego powiązania.

Dedykowany importer powiązania standardowego implementuje metodę ImportEndpoint w interfejsie IWsdlImportExtension, aby zbadać instancję CustomBinding zaimportowaną z metadanych i sprawdzić, czy mogła zostać wygenerowana 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 udostępnić nasz transport poprzez konfigurację, 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 to Configuration dla naszego SampleProfileUdpBinding.

Element wiążący, element rozszerzenia

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 wiązania

Sekcja SampleProfileUdpBindingCollectionElement jest elementem uwidacznianym StandardBindingCollectionElementSampleProfileUdpBinding w systemie konfiguracji. Większość implementacji jest delegowana do SampleProfileUdpBindingConfigurationElement, który pochodzi z StandardBindingElement. SampleProfileUdpBindingConfigurationElement ma właściwości odpowiadające właściwościom na SampleProfileUdpBinding, oraz funkcje do mapowania z powiązań ConfigurationElement. 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 w kodzie, a drugi za pomocą konfiguracji. Oba testy używają dwóch punktów końcowych. Jeden punkt końcowy używa SampleUdpProfileBinding z <reliableSession> ustawionym na true. Drugi punkt końcowy używa niestandardowego wiązania z elementem UdpTransportBindingElement. Jest to równoważne z użyciem SampleUdpProfileBinding z <reliableSession> ustawionym na false. 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 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ć aplikację kliencką testową dla 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ą widoczne 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ę kliencką dla punktów końcowych opublikowanych przy użyciu konfiguracji, naciśnij ENTER na 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ę serwisową, 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 SampleProfileUdpBinding, 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ładowy program

  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 Uruchamianie przykładów programu Windows Communication Foundation.

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