Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das UDP-Transportbeispiel veranschaulicht, wie UDP Unicast und Multicast als benutzerdefinierter WCF-Transport (Windows Communication Foundation) implementiert werden. Im Beispiel wird das empfohlene Verfahren zum Erstellen eines benutzerdefinierten Transports in WCF mithilfe des Kanalframeworks und der folgenden bewährten WCF-Methoden beschrieben. Die Schritte zum Erstellen eines benutzerdefinierten Transports lauten wie folgt:
Entscheiden Sie, welche der Kanalnachrichtenaustauschmuster (IOutputChannel, IInputChannel, IDuplexChannel, IRequestChannel oder IReplyChannel) Ihre ChannelFactory und ChannelListener unterstützen. Entscheiden Sie dann, ob Sie die Sitzungsvariationen dieser Schnittstellen unterstützen.
Erstellen Sie eine Kanalfactory und einen Listener, die Ihr Nachrichtenaustauschmuster unterstützen.
Sorgen Sie dafür, dass netzwerkspezifische Ausnahmen auf die passende abgeleitete Klasse von CommunicationException normalisiert werden.
Fügen Sie ein <Bindungselement> hinzu, das den benutzerdefinierten Transport zu einem Kanalstapel hinzufügt. Weitere Informationen finden Sie unter Hinzufügen eines Bindungselements.
Fügen Sie einen Erweiterungsabschnitt für Bindungselemente hinzu, um das neue Bindungselement für das Konfigurationssystem verfügbar zu machen.
Fügen Sie Metadatenerweiterungen hinzu, um Funktionen an andere Endpunkte zu kommunizieren.
Fügen Sie eine Bindung hinzu, die einen Stapel von Bindungselementen gemäß einem gut definierten Profil vorkonfiguriert. Weitere Informationen finden Sie unter Hinzufügen einer Standardbindung.
Fügen Sie einen Bindungsabschnitt und ein Bindungskonfigurationselement hinzu, um die Bindung für das Konfigurationssystem verfügbar zu machen. Weitere Informationen finden Sie unter Hinzufügen der Konfigurationsunterstützung.
Nachrichtenaustauschmuster
Der erste Schritt beim Schreiben eines benutzerdefinierten Transports besteht darin, zu entscheiden, welche Nachrichtenaustauschmuster (MEPs) für den Transport erforderlich sind. Es gibt drei Abgeordnete, aus denen Sie wählen können:
Datagramm (IInputChannel/IOutputChannel)
Bei Verwendung eines Datagramm-Nachrichtenaustauschmusters sendet ein Client eine Nachricht mit einem "fire and forget"-Austausch. Ein "fire and forget"-Austausch erfordert eine Out-of-Band-Bestätigung für die erfolgreiche Zustellung. Die Nachricht kann während der Übertragung verloren gehen und den Dienst nie erreichen. Wenn der Sendevorgang erfolgreich am Clientende abgeschlossen ist, garantiert er nicht, dass der Remoteendpunkt die Nachricht empfangen hat. Das Datagramm ist ein grundlegender Baustein für Messaging, da Sie ihre eigenen Protokolle darauf aufbauen können – einschließlich zuverlässiger Protokolle und sicherer Protokolle. Datagramm-Kanäle von Clients implementieren die IOutputChannel Schnittstelle und Datagramm-Kanäle von Diensten implementieren die IInputChannel Schnittstelle.
Anforderung-Antwort (IRequestChannel/IReplyChannel)
In diesem Nachrichtenaustauschmuster wird eine Nachricht gesendet, und eine Antwort wird empfangen. Das Muster besteht aus Anforderungsantwortpaaren. Beispiele für Anforderungsantwortaufrufe sind Remoteprozeduraufrufe (RPC) und Browser-GETs. Dieses Muster wird auch als Half-Duplex bezeichnet. In diesem Nachrichtenaustauschmuster implementieren Clientkanäle IRequestChannel, und Dienstkanäle implementieren IReplyChannel.
Duplex (IDuplexChannel)
Der Duplex-MEP ermöglicht eine beliebige Anzahl von Nachrichten, die von einem Client gesendet und in beliebiger Reihenfolge empfangen werden. Das Duplex-Nachrichtenaustauschmuster ist mit einem Telefongespräch vergleichbar, bei dem jedes gesprochene Wort einer Nachricht entspricht. Da beide Seiten in diesem MEP senden und empfangen können, ist die Schnittstelle, die von den Client- und Servicekanälen implementiert wird IDuplexChannel.
Jeder dieser Abgeordneten kann auch Sitzungen unterstützen. Die neue Funktion von sitzungsfähigen Kanälen besteht darin, dass alle in einem Kanal gesendeten und empfangenen Nachrichten korreliert werden. Das Anforderungs-Antwort-Muster ist eine eigenständige, aus zwei Nachrichten bestehende Sitzung, da die Anforderung und die Antwort korreliert werden. Im Gegensatz dazu impliziert das Request-Response Muster, das Sitzungen unterstützt, dass alle Anforderungs-/Antwortpaare in diesem Kanal miteinander korreliert werden. Dadurch ergeben sich sechs Nachrichtenaustauschmuster zur Auswahl: Datagramm, Anforderung-Antwort, Duplex, Datagramm mit Sitzungen, Anforderung-Antwort mit Sitzungen und Duplex mit Sitzungen.
Hinweis
Für den UDP-Transport wird nur das Nachrichtenaustauschmuster Datagramm unterstützt, da UDP grundsätzlich ein "fire and forget"-Protokoll ist.
Das ICommunicationObject und der WCF-Objektlebenszyklus
WCF hat einen allgemeinen Zustandsautomaten, der zum Verwalten des Legenszyklus von Objekten wie IChannel, IChannelFactory und IChannelListener verwendet wird, die der Kommunikation dienen. Es gibt fünf Zustände, in denen diese Kommunikationsobjekte vorhanden sein können. Diese Zustände werden durch die CommunicationState Enumeration dargestellt und sind wie folgt:
Erstellt: Dies ist der Zustand eines ICommunicationObject, wenn er zum ersten Mal instanziiert wird. In diesem Zustand tritt keine Eingabe/Ausgabe (E/A) auf.
Opening: Das Objekt geht zu diesem Zustand über, wenn Open aufgerufen wird. An diesem Punkt werden Eigenschaften unveränderlich gemacht, und die Eingabe/Ausgabe kann beginnen. Dieser Übergang ist nur vom Zustand "Erstellt" aus gültig.
Geöffnet: Objekte wechseln zu diesem Zustand, wenn der geöffnete Prozess abgeschlossen ist. Dieser Übergang ist nur vom Opening-Zustand aus gültig. Zu diesem Zeitpunkt kann das Objekt vollständig für die Übertragung verwendet werden.
Closing: Das Objekt geht zu diesem Zustand über, wenn Close für ein ordnungsgemäßes Herunterfahren aufgerufen wird. Dieser Übergang ist nur im Geöffneten Zustand gültig.
Geschlossen: Im Zustand "Geschlossen" können keine Objekte mehr verwendet werden. Im Allgemeinen ist die meisten Konfigurationen für die Inspektion immer noch zugänglich, aber es kann keine Kommunikation erfolgen. Dieser Zustand ist mit "Verworfen" vergleichbar.
Fehlerhaft: Im fehlerhaften Zustand sind Objekte für die Inspektion zugänglich, aber nicht mehr verwendbar. Wenn ein nicht wiederherstellbarer Fehler auftritt, wechselt das Objekt in diesen Zustand. Der einzige gültige Übergang von diesem Zustand ist in den
Closed
Zustand.
Es gibt Ereignisse, die für jeden Zustandsübergang ausgelöst werden. Die Abort Methode kann jederzeit aufgerufen werden und bewirkt, dass das Objekt sofort vom aktuellen Zustand in den Geschlossenen Zustand wechselt. Durch den Aufruf Abort werden alle nicht abgeschlossenen Arbeiten beendet.
Kanalfactory und Kanallistener
Der nächste Schritt beim Schreiben eines benutzerdefinierten Transports besteht darin, eine Implementierung für IChannelFactory Clientkanäle und für IChannelListener Dienstkanäle zu erstellen. Die Kanalebene verwendet ein Factorymuster zum Erstellen von Kanälen. WCF stellt Basisklassenhilfsprogramme für diesen Prozess bereit.
Die CommunicationObject Klasse implementiert ICommunicationObject und erzwingt die Zustandsmaschine, die zuvor in Schritt 2 beschrieben wurde.
Die ChannelManagerBase Klasse implementiert CommunicationObject und stellt eine einheitliche Basisklasse für ChannelFactoryBase und ChannelListenerBase. Die ChannelManagerBase-Klasse funktioniert in Verbindung mit ChannelBase, einer Basisklasse, die IChannel implementiert.
Die ChannelFactoryBase Klasse implementiert ChannelManagerBase und IChannelFactory konsolidiert die
CreateChannel
Überladungen in einerOnCreateChannel
abstrakten Methode.Die ChannelListenerBase Klasse implementiert IChannelListener. Die Klasse wird für grundlegende Zustandsverwaltung verwendet.
In diesem Beispiel ist die Factoryimplementierung in UdpChannelFactory.cs enthalten, und die Listenerimplementierung ist in UdpChannelListener.cs enthalten. Die IChannel Implementierungen befinden sich in UdpOutputChannel.cs und UdpInputChannel.cs.
Die UDP-Kanalerzeuger
Die UdpChannelFactory
wird von ChannelFactoryBase abgeleitet. Das Beispiel überschreibt GetProperty, um Zugriff auf die Nachrichtenversion des Nachrichtenencoders zu gewähren. Das Beispiel überschreibt auch OnClose, um beim Übergang des Zustandsautomaten die Instanz von BufferManager zu beenden.
Der UDP-Ausgabekanal
Der UdpOutputChannel
implementiert IOutputChannel. Der Konstruktor überprüft die Argumente und erstellt ein Zielobjekt EndPoint basierend auf dem EndpointAddress übergebenen Objekt.
this.socket = new Socket(this.remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
Der Kanal kann ordnungsgemäß oder nicht ordnungsgemäß geschlossen werden. Wird der Kanal ordnungsgemäß geschlossen, so wird der Socket geschlossen und ein Aufruf der Methode der Basisklasse OnClose
ausgeführt. Wenn dadurch eine Ausnahme ausgelöst wird, ruft die Infrastruktur auf Abort
, um sicherzustellen, dass der Kanal bereinigt wird.
this.socket.Close(0);
Wir implementieren dann Send()
und BeginSend()
/EndSend()
. Dies unterteilt sich in zwei Hauptabschnitte. Zuerst serialisieren wir die Nachricht in ein Bytearray.
ArraySegment<byte> messageBuffer = EncodeMessage(message);
Dann senden wir die resultierenden Daten über das Netzwerk.
this.socket.SendTo(messageBuffer.Array, messageBuffer.Offset, messageBuffer.Count, SocketFlags.None, this.remoteEndPoint);
Der UdpChannelListener
Die UdpChannelListener
-Implementierung im Beispiel wird von der ChannelListenerBase-Klasse abgeleitet. Es verwendet einen einzelnen UDP-Socket, um Datagramme zu empfangen. Die OnOpen
Methode empfängt Daten mithilfe des UDP-Sockets in einer asynchronen Schleife. Die Daten werden dann mithilfe des Nachrichtencodierungsframeworks in Nachrichten konvertiert.
message = MessageEncoderFactory.Encoder.ReadMessage(new ArraySegment<byte>(buffer, 0, count), bufferManager);
Da derselbe Datagrammkanal Nachrichten darstellt, die aus einer Reihe von Quellen eingehen, ist dies UdpChannelListener
ein Singleton-Listener. Es gibt höchstens einen aktiven IChannel, der diesem Listener gleichzeitig zugeordnet ist. In diesem Beispiel wird nur dann ein weiterer generiert, wenn ein Kanal, der mit der AcceptChannel
-Methode zurückgegeben wird, anschließend freigegeben wird. Wenn eine Nachricht empfangen wird, wird sie in diesem Singletonkanal in die Warteschlange eingereiht.
UdpEingabekanal
Die UdpInputChannel
Klasse implementiert IInputChannel
. Sie besteht aus einer Warteschlange mit eingehenden Nachrichten, die vom Socket UdpChannelListener
aufgefüllt wird. Diese Nachrichten werden mit der IInputChannel.Receive
-Methode aus der Warteschlange entfernt.
Hinzufügen eines Binding-Elements
Nachdem nun die Factorys und Kanäle erstellt sind, müssen sie der ServiceModel-Laufzeit über eine Bindung verfügbar gemacht werden. Eine Bindung ist eine Sammlung von Bindungselementen, die den Kommunikationsstapel darstellen, der einer Dienstadresse zugeordnet ist. Jedes Element im Stapel wird durch ein <Bindungselement> dargestellt.
Im Beispiel ist das Bindungselement UdpTransportBindingElement
, das sich von TransportBindingElement ableitet. Es überschreibt die folgenden Methoden zum Erstellen der der Bindung zugeordneten Factorys.
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);
}
Es enthält auch Member zum Klonen des BindingElement
und Zurückgeben unseres Schemas (soap.udp).
Hinzufügen der Metadatenunterstützung für ein Transport-Binding-Element
Um unseren Transport in das Metadatensystem zu integrieren, müssen wir sowohl den Import als auch den Export von Richtlinien unterstützen. Auf diese Weise können wir Kunden unserer Bindung über das ServiceModel Metadata Utility Tool (Svcutil.exe) generieren.
Hinzufügen der WSDL-Unterstützung
Das Transportbindungselement in einer Bindung ist für das Exportieren und Importieren von Adressierungsinformationen in Metadaten verantwortlich. Bei Verwendung einer SOAP-Bindung sollte das Transportbindungselement auch einen korrekten Transport-URI in Metadaten exportieren.
WSDL-Export
Zum Exportieren von Adressinformationen implementiert die UdpTransportBindingElement
die IWsdlExportExtension
Schnittstelle. Die ExportEndpoint
Methode fügt dem WSDL-Port die richtigen Adressierungsinformationen hinzu.
if (context.WsdlPort != null)
{
AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);
}
Die UdpTransportBindingElement
Implementierung der ExportEndpoint
Methode exportiert auch einen Transport-URI, wenn der Endpunkt eine SOAP-Bindung verwendet.
WsdlNS.SoapBinding soapBinding = GetSoapBinding(context, exporter);
if (soapBinding != null)
{
soapBinding.Transport = UdpPolicyStrings.UdpNamespace;
}
WSDL-Import
Um das WSDL-Importsystem zum Importieren der Adressen zu erweitern, müssen wir der Konfigurationsdatei die folgende Konfiguration für Svcutil.exe hinzufügen, wie in der Svcutil.exe.config-Datei dargestellt.
<configuration>
<system.serviceModel>
<client>
<metadata>
<policyImporters>
<extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
Beim Ausführen von Svcutil.exegibt es zwei Optionen, um Svcutil.exe zum Laden der WSDL-Importerweiterungen zu bringen:
Verweisen Sie „Svcutil.exe“ mit „/SvcutilConfig:<Datei>“ auf unsere Konfigurationsdatei.
Fügen Sie den Konfigurationsabschnitt zu Svcutil.exe.config im selben Verzeichnis wie Svcutil.exehinzu.
Der UdpBindingElementImporter
Typ implementiert die IWsdlImportExtension
Schnittstelle. Die ImportEndpoint
Methode importiert die Adresse aus dem WSDL-Port.
BindingElementCollection bindingElements = context.Endpoint.Binding.CreateBindingElements();
TransportBindingElement transportBindingElement = bindingElements.Find<TransportBindingElement>();
if (transportBindingElement is UdpTransportBindingElement)
{
ImportAddress(context);
}
Hinzufügen von Richtlinienunterstützung
Das benutzerdefinierte Bindungselement kann Richtlinien-Assertions in der WSDL-Bindung für einen Service-Endpunkt exportieren, um die Eigenschaften dieses Bindungselements auszudrücken.
Richtlinienexport
Der UdpTransportBindingElement
-Typ implementiert IPolicyExportExtension
, um den Export von Richtlinien zu unterstützen. Als Ergebnis schließt System.ServiceModel.MetadataExporter
UdpTransportBindingElement
in die Generierung der Richtlinie für eine Bindung ein, die dieses enthält.
In IPolicyExportExtension.ExportPolicy
fügen wir eine Assertion für UDP hinzu und eine weitere, wenn wir uns im Multicast-Modus befinden. Dies liegt daran, dass sich der Multicastmodus auf die Konstruktion des Kommunikationsstapels auswirkt und somit zwischen beiden Seiten koordiniert werden muss.
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));
}
Da benutzerdefinierte Transportbindungselemente für die Handhabung der Adressierung verantwortlich sind, muss die IPolicyExportExtension
-Implementierung auf dem UdpTransportBindingElement
auch den Export der geeigneten WS-Adressierungsrichtlinienassertionen handhaben, um die Version der verwendeten WS-Adressierung anzugeben.
AddWSAddressingAssertion(context, encodingBindingElement.MessageVersion.Addressing);
Richtlinienimport
Um das Richtlinienimportsystem zu erweitern, müssen wir der Konfigurationsdatei die folgende Konfiguration für Svcutil.exe hinzufügen, wie in der Svcutil.exe.config-Datei dargestellt.
<configuration>
<system.serviceModel>
<client>
<metadata>
<policyImporters>
<extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
Anschließend implementieren wir IPolicyImporterExtension
aus unserer registrierten Klasse (UdpBindingElementImporter
). Prüfen Sie in ImportPolicy()
die Assertionen im entsprechenden Namespace, verarbeiten Sie sie für die Generierung des Transports, und prüfen Sie, ob Multicast vorliegt. Wir müssen auch die Assertionen, die wir behandeln, aus der Liste der verbindlichen Assertionen entfernen. Erneut stehen bei der Ausführung von "Svcutil.exe" zwei Optionen für die Integration zur Verfügung:
Verweisen Sie „Svcutil.exe“ mit „/SvcutilConfig:<Datei>“ auf unsere Konfigurationsdatei.
Fügen Sie den Konfigurationsabschnitt zu Svcutil.exe.config im selben Verzeichnis wie Svcutil.exehinzu.
Hinzufügen einer Standardbindung
Unser Bindungselement kann auf folgende zwei Arten verwendet werden:
Über eine benutzerdefinierte Bindung: Mit einer benutzerdefinierten Bindung kann der Benutzer eine eigene Bindung basierend auf einer beliebigen Gruppe von Bindungselementen erstellen.
Mithilfe einer vom System bereitgestellten Bindung, die unser Bindungselement enthält. WCF stellt eine Reihe dieser vom System definierten Bindungen bereit, z. B.
BasicHttpBinding
,NetTcpBinding
undWsHttpBinding
. Jede dieser Bindungen ist einem klar definierten Profil zugeordnet.
Im Beispiel wird die Profilbindung in SampleProfileUdpBinding
implementiert, die von Binding abgeleitet wird. Das SampleProfileUdpBinding
Enthält bis zu vier Bindungselemente darin: UdpTransportBindingElement
, , TextMessageEncodingBindingElement CompositeDuplexBindingElement
und 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();
}
Hinzufügen eines benutzerdefinierten Standardbindungsimportprogramms
Svcutil.exe und der WsdlImporter
Typ erkennt und importiert standardmäßig systemdefinierte Bindungen. Andernfalls wird die Bindung als CustomBinding
Instanz importiert. Zur Aktivierung des Imports der WsdlImporter
für „Svcutil.exe“ und den SampleProfileUdpBinding
, fungiert der UdpBindingElementImporter
auch als benutzerdefiniertes Importprogramm für Standardbindungen.
Ein benutzerdefinierter Standardbindungsimporteur implementiert die ImportEndpoint
Methode auf der IWsdlImportExtension
Schnittstelle, um die CustomBinding
aus Metadaten importierte Instanz zu untersuchen, um festzustellen, ob sie durch eine bestimmte Standardbindung generiert worden sein könnte.
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;
}
}
}
Im Allgemeinen umfasst die Implementierung eines benutzerdefinierten Standardbindungsimporteurs die Überprüfung der Eigenschaften der importierten Bindungselemente, um zu überprüfen, ob nur Eigenschaften, die durch die Standardbindung festgelegt werden konnten, geändert wurden und alle anderen Eigenschaften ihre Standardwerte sind. Eine grundlegende Strategie für die Implementierung eines Standardbindungsimporteurs besteht darin, eine Instanz der Standardbindung zu erstellen, die Eigenschaften von den Bindungselementen an die Standardbindungsinstanz zu verteilen, die von der Standardbindung unterstützt wird, und die Bindungselemente aus der Standardbindung mit den importierten Bindungselementen zu vergleichen.
Hinzufügen der Konfigurationsunterstützung
Um unseren Transport durch Konfiguration verfügbar zu machen, müssen Sie zwei Konfigurationsabschnitte implementieren. Der erste ist ein BindingElementExtensionElement
für UdpTransportBindingElement
. Dies ist so, dass CustomBinding
Implementierungen auf unser Bindungselement verweisen können. Der zweite ist eine Configuration
für SampleProfileUdpBinding
.
Element für Bindungselementerweiterungen
Der Abschnitt UdpTransportElement
ist ein BindingElementExtensionElement
, der UdpTransportBindingElement
dem Konfigurationssystem zur Verfügung stellt. Mit einigen grundlegenden Anpassungen definieren wir unseren Konfigurationsabschnittsnamen, den Typ unseres Bindungselements und wie wir unser Bindungselement erstellen. Anschließend können wir unseren Erweiterungsabschnitt in einer Konfigurationsdatei registrieren, wie im folgenden Code gezeigt.
<configuration>
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="udpTransport" type="Microsoft.ServiceModel.Samples.UdpTransportElement, UdpTransport" />
</bindingElementExtensions>
</extensions>
</system.serviceModel>
</configuration>
Auf die Erweiterung kann von benutzerdefinierten Bindungen verwiesen werden, um UDP als Transport zu verwenden.
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding configurationName="UdpCustomBinding">
<udpTransport/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
Bindungsabschnitt
Der Abschnitt SampleProfileUdpBindingCollectionElement
ist ein StandardBindingCollectionElement
, der SampleProfileUdpBinding
dem Konfigurationssystem zur Verfügung stellt. Der Großteil der Implementierung wird an das SampleProfileUdpBindingConfigurationElement
delegiert, das von StandardBindingElement
abgeleitet ist.
SampleProfileUdpBindingConfigurationElement
verfügt über Eigenschaften, die den SampleProfileUdpBinding
-Eigenschaften entsprechen, sowie über Funktionen für die Zuordnung aus der ConfigurationElement
-Bindung. Überschreiben Sie schließlich die OnApplyConfiguration
-Methode in unserem SampleProfileUdpBinding
, wie im folgenden Beispielcode gezeigt.
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;
}
Um diesen Handler beim Konfigurationssystem zu registrieren, fügen wir der relevanten Konfigurationsdatei den folgenden Abschnitt hinzu.
<configuration>
<configSections>
<sectionGroup name="system.serviceModel">
<sectionGroup name="bindings">
<section name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />
</sectionGroup>
</sectionGroup>
</configSections>
</configuration>
Auf sie kann dann über den ServiceModel-Konfigurationsabschnitt verwiesen werden.
<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>
Der UDP-Testdienst und -Client
Testcode für die Verwendung dieses Beispieltransports ist in den Verzeichnissen UdpTestService und UdpTestClient verfügbar. Der Dienstcode besteht aus zwei Tests: ein Test richtet Bindungen und Endpunkte aus Code ein, und die andere führt ihn über die Konfiguration aus. Beide Tests verwenden zwei Endpunkte. Ein Endpunkt verwendet SampleUdpProfileBinding
mit der Festlegung von <reliableSession> auf true
. Der andere Endpunkt verwendet eine benutzerdefinierte Bindung mit UdpTransportBindingElement
. Dies entspricht der Verwendung von SampleUdpProfileBinding
mit der Festlegung von <reliableSession> auf false
. Beide Tests erstellen einen Dienst, fügen einen Endpunkt für jede Bindung hinzu, öffnen den Dienst und warten dann, bis der Benutzer die EINGABETASTE erreicht hat, bevor der Dienst geschlossen wird.
Wenn Sie die Diensttestanwendung starten, sollte die folgende Ausgabe angezeigt werden.
Testing Udp From Code.
Service is started from code...
Press <ENTER> to terminate the service and start service from config...
Anschließend können Sie die Testclientanwendung für die veröffentlichten Endpunkte ausführen. Die Clienttestanwendung erstellt einen Client für jeden Endpunkt und sendet fünf Nachrichten an jeden Endpunkt. Im Folgenden finden Sie die Ausgabe auf dem Client:
Testing Udp From Imported Files Generated By SvcUtil.
0
3
6
9
12
Press <ENTER> to complete test.
Im Folgenden finden Sie die vollständige Ausgabe auf dem Dienst:
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
Um die Clientanwendung gegen Endpunkte auszuführen, die mit Konfiguration veröffentlicht wurden, drücken Sie die EINGABETASTE, um den Dienst zu starten, und führen Sie den Testclient erneut aus. Auf dem Dienst sollten Sie die folgende Ausgabe erhalten:
Testing Udp From Config.
Service is started from config...
Press <ENTER> to terminate the service and exit...
Wenn der Client erneut ausgeführt wird, wird dasselbe wie die vorherigen Ergebnisse erzielt.
Um den Clientcode und die Konfiguration mithilfe von Svcutil.exeneu zu generieren, starten Sie die Dienstanwendung, und führen Sie dann die folgenden Svcutil.exe aus dem Stammverzeichnis des Beispiels aus.
svcutil http://localhost:8000/udpsample/ /reference:UdpTransport\bin\UdpTransport.dll /svcutilConfig:svcutil.exe.config
Beachten Sie, dass Svcutil.exe die Bindungserweiterungskonfiguration für die SampleProfileUdpBinding
Datei nicht generiert, sodass Sie sie manuell hinzufügen müssen.
<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>
So können Sie das Beispiel einrichten, erstellen und ausführen
Befolgen Sie zum Erstellen der Lösung die Anweisungen im Erstellen der Windows Communication Foundation-Beispiele.
Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.
Weitere Informationen finden Sie im vorherigen Abschnitt "Udp Test Service and Client".