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:
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.
Utwórz fabrykę kanałów i odbiornik obsługujący wzorzec wymiany komunikatów.
Upewnij się, że wszystkie wyjątki specyficzne dla sieci są znormalizowane do odpowiedniej klasy pochodnej klasy CommunicationException.
<Dodaj element powiązania>, który dodaje niestandardowy transport do stosu kanału. Aby uzyskać więcej informacji, zobacz Dodawanie elementu powiązania.
Dodaj sekcję rozszerzenia elementu powiązania, aby uwidocznić nowy element powiązania w systemie konfiguracji.
Dodaj rozszerzenia metadanych, aby komunikować się z innymi punktami końcowymi.
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.
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.
Klasa CommunicationObject implementuje ICommunicationObject i wymusza maszynę stanu opisaną wcześniej w kroku 2.
Klasa ChannelManagerBase implementuje CommunicationObject i udostępnia ujednoliconą klasę bazową dla elementów ChannelFactoryBase i ChannelListenerBase. Klasa ChannelManagerBase działa w połączeniu z klasą ChannelBase, która jest klasą bazową, która implementuje IChannelelement .
Klasa ChannelFactoryBase implementuje ChannelManagerBase i IChannelFactory konsoliduje
CreateChannel
przeciążenia w jednąOnCreateChannel
metodę abstrakcyjną.Klasa ChannelListenerBase implementuje IChannelListenerelement . Zajmuje się podstawowym zarządzaniem stanem.
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 UdpOutputChannel
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, 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 IInputChannel
element . Składa się z kolejki komunikatów przychodzących wypełnianych przez UdpChannelListener
gniazdo . 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 UdpTransportBindingElement
ExportEndpoint
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:
Wskaż Svcutil.exe do pliku konfiguracji przy użyciu pliku /SvcutilConfig:<file>.
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.ExportPolicy
systemie 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:
Wskaż Svcutil.exe do pliku konfiguracji przy użyciu pliku /SvcutilConfig:<file>.
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
,NetTcpBinding
iWsHttpBinding
. 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 CompositeDuplexBindingElement
i 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, SampleProfileUdpBinding
UdpBindingElementImporter
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 UdpTransportBindingElement
elementu . Dzięki temu CustomBinding
implementacje mogą odwoływać się do naszego elementu powiązania. Drugi jest elementem Configuration
dla naszego SampleProfileUdpBinding
elementu .
Binding, element extension, element
Sekcja UdpTransportElement
jest elementem uwidacznianym BindingElementExtensionElement
UdpTransportBindingElement
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 StandardBindingCollectionElement
SampleProfileUdpBinding
w systemie konfiguracji. Większość implementacji jest delegowana do SampleProfileUdpBindingConfigurationElement
klasy , która pochodzi z klasy StandardBindingElement
. Zawiera SampleProfileUdpBindingConfigurationElement
właściwości, które odpowiadają właściwościom elementu SampleProfileUdpBinding
i 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 true
wartość . 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 false
wartość . 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 SampleProfileUdpBinding
elementu , 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
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).
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.
Zapoznaj się z poprzednią sekcją "Usługa testowa UDP i klient".