Een Berichtuitwisselingspatroon kiezen
De eerste stap bij het schrijven van een aangepast transport is om te bepalen welke berichtuitwisselingspatronen (of EP-leden) vereist zijn voor het kanaal dat u ontwikkelt. In dit onderwerp worden de beschikbare opties beschreven en worden de verschillende vereisten besproken. Dit is de eerste taak in de lijst met kanaalontwikkelingstaken die worden beschreven in Kanalen ontwikkelen.
Zes patronen voor berichtuitwisseling
Er zijn drie parlementsleden waaruit u kunt kiezen:
Datagram (IInputChannel en IOutputChannel)
Wanneer u een datagram MEP gebruikt, verzendt een client een bericht met behulp van een brand en vergeet uitwisseling. Een brand en vergeet uitwisseling is een die out-of-band bevestiging van geslaagde levering vereist. Het bericht gaat mogelijk verloren tijdens de overdracht en bereikt nooit de service. Als de verzendbewerking is voltooid aan het clienteindpunt, wordt niet gegarandeerd dat het externe eindpunt het bericht heeft ontvangen. Het datagram is een fundamentele bouwsteen voor berichten, omdat u er uw eigen protocollen op kunt bouwen, inclusief betrouwbare protocollen en veilige protocollen. Client datagram kanalen implementeren de IOutputChannel interface en service datagram kanalen implementeren de IInputChannel interface.
Aanvraag-antwoord (IRequestChannel en IReplyChannel)
In dit MEP wordt een bericht verzonden en wordt er een antwoord ontvangen. Het patroon bestaat uit aanvraag-antwoordparen. Voorbeelden van aanvragen-antwoordoproepen zijn externe procedure-aanroepen (RPC) en GET-aanvragen voor browsers. Dit patroon wordt ook wel half-duplex genoemd. In dit MEP implementeren IRequestChannel en servicekanalen clientkanalen implementeren IReplyChannel.
Duplex (IDuplexChannel)
Met het duplex-MEP kan een willekeurig aantal berichten worden verzonden door een client en in elke willekeurige volgorde worden ontvangen. Het duplex-MEP is net als een telefoongesprek, waarbij elk woord dat wordt gesproken een bericht is. Omdat beide zijden in dit MEP kunnen verzenden en ontvangen, is de interface die door de client- en servicekanalen wordt IDuplexChannelgeïmplementeerd.
De drie basispatronen voor het uitwisselen van berichten. Van boven naar beneden: datagram, request-response en duplex.
Elk van deze leden kan ook sessies ondersteunen. Een sessie (en implementatie van het System.ServiceModel.Channels.ISessionChannel<TSession> type System.ServiceModel.Channels.ISession) correleert alle berichten die op een kanaal worden verzonden en ontvangen. Het aanvraag-antwoordpatroon is een zelfstandige sessie met twee berichten, omdat de aanvraag en het antwoord gecorreleerd zijn. Het aanvraag-antwoordpatroon dat sessies ondersteunt, houdt daarentegen in dat alle aanvraag-/antwoordparen op dat kanaal met elkaar zijn gecorreleerd. Dit geeft u in totaal zes afgevaardigden waaruit u kunt kiezen:
Datagram
Aanvraag-antwoord
Duplex
Datagram met sessies
Aanvraagantwoord met sessies
Dubbelzijdig met sessies
Notitie
Voor het UDP-transport is het enige MEP dat wordt ondersteund datagram, omdat UDP inherent een brand- en vergeetprotocol is.
Sessies en sessionful kanalen
In de netwerkwereld zijn er verbindingsgeoriënteerde protocollen (bijvoorbeeld TCP) en protocollen voor verbindingsloze verbindingen (bijvoorbeeld UDP). WCF gebruikt de term sessie om een verbinding-achtige logische abstractie te betekenen. Sessionful WCF-protocollen zijn vergelijkbaar met verbindingsgeoriënteerde netwerkprotocollen en sessieloze WCF-protocollen zijn vergelijkbaar met verbindingsloze netwerkprotocollen.
In het kanaalobjectmodel worden elke logische sessiemanifesten weergegeven als een exemplaar van een sessionful-kanaal. Daarom komt elke nieuwe sessie die door de client is gemaakt en geaccepteerd op de service, overeen met een nieuw sessievol kanaal aan elke kant. In het volgende diagram ziet u bovenaan de structuur van sessieloze kanalen en onderaan de structuur van sessieloze kanalen.
Een client maakt een nieuw sessionful-kanaal en verzendt een bericht. Aan de servicezijde ontvangt de kanaallistener dit bericht en detecteert dat het deel uitmaakt van een nieuwe sessie, zodat er een nieuw sessievol kanaal wordt gemaakt en aan de toepassing wordt overhandigd (in reactie op de toepassing die AcceptChannel aanroept op de kanaallistener). De toepassing ontvangt vervolgens dit bericht en alle volgende berichten die in dezelfde sessie worden verzonden via hetzelfde sessieful kanaal.
Een andere client (of dezelfde client) maakt een nieuwe sessieful en verzendt een bericht. De kanaallistener detecteert dat dit bericht zich in een nieuwe sessie bevindt en maakt een nieuw sessieful kanaal en het proces wordt herhaald.
Zonder sessies is er geen correlatie tussen kanalen en sessies. Daarom maakt een kanaallistener slechts één kanaal waarmee alle ontvangen berichten aan de toepassing worden bezorgd. Er is ook geen berichtvolgorde omdat er geen sessie is waarin de berichtvolgorde wordt bijgehouden. Het bovenste gedeelte van de voorgaande afbeelding illustreert een sessieloze berichtuitwisseling.
Sessies starten en beëindigen
Sessies worden gestart op de client door simpelweg een nieuw sessieful kanaal te maken. Ze worden gestart op de service wanneer de service een bericht ontvangt dat in een nieuwe sessie is verzonden. Op dezelfde manier worden sessies beëindigd door een sessievol kanaal te sluiten of af te breken.
De uitzondering hierop is IDuplexSessionChannel dat deze wordt gebruikt voor het verzenden en ontvangen van berichten in een dubbelzijdig communicatiepatroon met sessiebeheer. Het is mogelijk dat de ene kant het verzenden van berichten wil stoppen, maar berichten blijft ontvangen. Daarom IDuplexSessionChannel is er een mechanisme waarmee u de uitvoersessie kunt sluiten die aangeeft dat u geen berichten meer wilt verzenden, maar de invoersessie geopend houdt, zodat u berichten kunt blijven ontvangen.
Over het algemeen worden sessies gesloten aan de uitgaande zijde en niet aan de binnenkomende zijde. Dat wil gezegd, sessieful uitvoerkanalen kunnen worden gesloten, waardoor de sessie op een schone manier wordt beëindigd. Als u een sessieful uitvoerkanaal sluit, wordt het bijbehorende sessieful invoerkanaal null geretourneerd naar de toepassing die wordt aangeroepen IInputChannel.Receive op de IDuplexSessionChanneltoepassing.
Sessieful invoerkanalen mogen echter niet worden gesloten, tenzij IInputChannel.Receive op de IDuplexSessionChannel retourneert null, waarmee wordt aangegeven dat de sessie al is gesloten. Als IInputChannel.Receive op de IDuplexSessionChannel functie null niet is geretourneerd, kan het sluiten van een sessievol invoerkanaal een uitzondering veroorzaken omdat er mogelijk onverwachte berichten worden ontvangen tijdens het sluiten. Als een ontvanger een sessie wil beëindigen voordat de afzender dat doet, moet deze het invoerkanaal aanroepen Abort , waardoor de sessie plotseling wordt beëindigd.
Sessionful-kanalen schrijven
Als sessieful kanaalauteur zijn er enkele dingen die uw kanaal moet doen om sessies te bieden. Aan de verzendzijde moet uw kanaal het volgende doen:
Maak voor elk nieuw kanaal een nieuwe sessie en koppel deze aan een nieuwe sessie-id. Dit is een unieke tekenreeks. Of haal een nieuwe sessie op via het sessionful-kanaal onder u in de stack.
Voor elk bericht dat via dit kanaal wordt verzonden, moet u het bericht koppelen aan de sessie als uw kanaal de sessie heeft gemaakt (in tegenstelling tot het verkrijgen van het bericht uit de laag eronder). Voor protocolkanalen wordt dit meestal gedaan door een SOAP-header toe te voegen. Voor transportkanalen wordt dit meestal gedaan door een nieuwe transportverbinding te maken of sessiegegevens toe te voegen aan het frameprotocol.
Voor elk bericht dat via dit kanaal wordt verzonden, moet u de bovenstaande leveringsgaranties opgeven. Als u vertrouwt op het onderstaande kanaal om de sessie te leveren, biedt dat kanaal ook de leveringsgaranties. Als u de sessie zelf opgeeft, moet u deze garanties implementeren als onderdeel van uw protocol. Als u over het algemeen een protocolkanaal schrijft waarin wordt uitgegaan van WCF aan beide zijden, is het mogelijk dat u het TCP-transport of het Reliable Messaging-kanaal vereist en vertrouwt op een van beide kanalen om een sessie te bieden.
Wanneer ICommunicationObject.Close het kanaal wordt aangeroepen, voert u het benodigde werk uit om de sessie te sluiten met behulp van de opgegeven time-out of de standaardtime-out. Dit kan net zo eenvoudig zijn als bellen Close op het kanaal hieronder (als u zojuist de sessie hebt verkregen) of een speciaal SOAP-bericht verzendt of een transportverbinding sluit.
Wanneer Abort wordt aangeroepen op uw kanaal, beëindigt u de sessie plotseling zonder I/O uit te voeren. Dit kan betekenen dat u niets doet of dat een netwerkverbinding of een andere resource wordt afgebroken.
Aan de ontvangstzijde moet uw kanaal het volgende doen:
Voor elk binnenkomend bericht moet de kanaallistener de sessie detecteren waartoe het behoort. Als dit het eerste bericht in de sessie is, moet de kanaallistener een nieuw kanaal maken en dit retourneren van de aanroep naar IChannelListener<TChannel>.AcceptChannel. Anders moet de kanaallistener het bestaande kanaal vinden dat overeenkomt met de sessie en het bericht via dat kanaal bezorgen.
Als uw kanaal de sessie (samen met de vereiste leveringsgaranties) levert, kan het zijn dat de ontvangstzijde bepaalde acties moet uitvoeren, zoals berichten opnieuw ordenen of bevestigingen verzenden.
Wanneer Close het kanaal wordt aangeroepen, voert u het benodigde werk uit om de sessie te sluiten van de opgegeven time-out of de standaardtime-out. Dit kan leiden tot uitzonderingen als het kanaal een bericht ontvangt terwijl wordt gewacht tot de time-out voor sluiten is verlopen. Dat komt doordat het kanaal de status Sluiten heeft wanneer het een bericht ontvangt, zodat het zou worden gegooid.
Wanneer Abort wordt aangeroepen op uw kanaal, beëindigt u de sessie plotseling zonder I/O uit te voeren. Dit kan ook betekenen dat er niets gebeurt of dat een netwerkverbinding of een andere resource wordt afgebroken.