Freigeben über


Transport: UDP

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:

  1. 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.

  2. Erstellen Sie eine Kanalfactory und einen Listener, die Ihr Nachrichtenaustauschmuster unterstützen.

  3. Sorgen Sie dafür, dass netzwerkspezifische Ausnahmen auf die passende abgeleitete Klasse von CommunicationException normalisiert werden.

  4. Fügen Sie ein <Bindungselement> hinzu, das den benutzerdefinierten Transport zu einem Kanalstapel hinzufügt. Weitere Informationen finden Sie unter Hinzufügen eines Bindungselements.

  5. Fügen Sie einen Erweiterungsabschnitt für Bindungselemente hinzu, um das neue Bindungselement für das Konfigurationssystem verfügbar zu machen.

  6. Fügen Sie Metadatenerweiterungen hinzu, um Funktionen an andere Endpunkte zu kommunizieren.

  7. 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.

  8. 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.

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:

  1. Verweisen Sie „Svcutil.exe“ mit „/SvcutilConfig:<Datei>“ auf unsere Konfigurationsdatei.

  2. 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.MetadataExporterUdpTransportBindingElement 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:

  1. Verweisen Sie „Svcutil.exe“ mit „/SvcutilConfig:<Datei>“ auf unsere Konfigurationsdatei.

  2. 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 und WsHttpBinding. 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 CompositeDuplexBindingElementund 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 SampleProfileUdpBindingDatei 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

  1. Befolgen Sie zum Erstellen der Lösung die Anweisungen im Erstellen der Windows Communication Foundation-Beispiele.

  2. 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.

  3. Weitere Informationen finden Sie im vorherigen Abschnitt "Udp Test Service and Client".