Dela via


Välja ett Exchange-meddelandemönster

Det första steget i att skriva en anpassad transport är att bestämma vilka mönster för meddelandeutbyte (eller parlamentsledamöter) som krävs för den kanal som du utvecklar. Det här avsnittet beskriver de tillgängliga alternativen och beskriver de olika kraven. Det här är den första uppgiften i aktivitetslistan för kanalutveckling som beskrivs i Utveckla kanaler.

Six Message Exchange Patterns

Det finns tre parlamentsledamöter att välja mellan:

  • Datagram (IInputChannel och IOutputChannel)

    När du använder en datagram-MEP skickar en klient ett meddelande med hjälp av en brand och glömmer utbyte. En brand och glöm utbyte är en som kräver out-of-band bekräftelse av lyckad leverans. Meddelandet kan gå förlorat under överföring och aldrig nå tjänsten. Om sändningsåtgärden har slutförts i klientdelen garanterar den inte att fjärrslutpunkten har tagit emot meddelandet. Datagrammet är en grundläggande byggsten för meddelanden, eftersom du kan skapa egna protokoll ovanpå det, inklusive tillförlitliga protokoll och säkra protokoll. Klientdatagramkanaler implementerar IOutputChannel gränssnittet och tjänstens datagramkanaler implementerar IInputChannel gränssnittet.

  • Begärandesvar (IRequestChannel och IReplyChannel)

    I denna parlamentsledamot skickas ett meddelande och ett svar tas emot. Mönstret består av par för begäran-svar. Exempel på begärandesvarsanrop är fjärrproceduranrop (RPC) och get-begäranden i webbläsaren. Det här mönstret kallas även för halv duplex. I denna MEP implementerar IRequestChannel klientkanaler och tjänstkanaler implementerar IReplyChannel.

  • Duplex (IDuplexChannel)

    Duplex-PARP tillåter att ett godtyckligt antal meddelanden skickas av en klient och tas emot i valfri ordning. Parparlamentarikern är som ett telefonsamtal, där varje ord som talas är ett meddelande. Eftersom båda sidor kan skicka och ta emot i denna Parlamentsledamot är IDuplexChannelgränssnittet som implementeras av klient- och tjänstkanalerna .

Flowchart showing the three basic message exchange patterns
De tre grundläggande mönster för meddelandeutbyte. Uppifrån och ned: datagram, begärandesvar och duplex.

Var och en av dessa parlamentsledamöter kan också stödja sessioner. En session (och implementering av System.ServiceModel.Channels.ISessionChannel<TSession> typen System.ServiceModel.Channels.ISession) korrelerar alla meddelanden som skickas och tas emot på en kanal. Mönstret för begäran-svar är en fristående session med två meddelanden, eftersom begäran och svar korreleras. Däremot innebär mönstret för begäran-svar som stöder sessioner att alla par för begäran/svar på kanalen är korrelerade med varandra. Detta ger dig totalt sex parlamentsledamöter att välja mellan:

  • Datagram

  • Begärandesvar

  • Duplex

  • Datagram med sessioner

  • Begärandesvar med sessioner

  • Duplex med sessioner

Kommentar

För UDP-transporten är den enda parlamentsledamot som stöds datagram, eftersom UDP i sig är ett protokoll för brand och glöms bort.

Sessioner och sessionskänsliga kanaler

I nätverksvärlden finns anslutningsorienterade protokoll (till exempel TCP) och anslutningslösa protokoll (till exempel UDP). WCF använder termen session för att betyda en anslutningsliknande logisk abstraktion. Sessionskänsliga WCF-protokoll liknar anslutningsorienterade nätverksprotokoll och sessionslösa WCF-protokoll liknar anslutningslösa nätverksprotokoll.

I kanalobjektmodellen visas varje logisk session som en instans av en sessionskänslig kanal. Därför motsvarar varje ny session som skapas av klienten och accepteras i tjänsten en ny sessionskänslig kanal på varje sida. I följande diagram visas strukturen för sessionslösa kanaler längst upp och längst ned i strukturen för sessionskänsliga kanaler.

Flowchart showing the structure of sessionless and sessionful channels

En klient skapar en ny sessionskänslig kanal och skickar ett meddelande. På tjänstsidan tar kanallyssnaren emot det här meddelandet och identifierar att det tillhör en ny session så att den skapar en ny sessionskänslig kanal och ger den till programmet (som svar på programmet som anropar AcceptChannel på kanallyssnaren). Programmet tar sedan emot det här meddelandet och alla efterföljande meddelanden som skickas i samma session via samma sessionskänsliga kanal.

En annan klient (eller samma klient) skapar en ny sessionful och skickar ett meddelande. Kanallyssnaren upptäcker att det här meddelandet finns i en ny session och skapar en ny sessionskänslig kanal och processen upprepas.

Utan sessioner finns det ingen korrelation mellan kanaler och sessioner. Därför skapar en kanallyssnare bara en kanal genom vilken alla mottagna meddelanden levereras till programmet. Det finns inte heller någon meddelandeordning eftersom det inte finns någon session där meddelandeordningen ska underhållas. Den översta delen av föregående bild illustrerar ett sessionslöst meddelandeutbyte.

Starta och avsluta sessioner

Sessioner startas på klienten genom att helt enkelt skapa en ny sessionskänslig kanal. De startas i tjänsten när tjänsten tar emot ett meddelande som skickades i en ny session. På samma sätt avslutas sessioner genom att stänga eller avbryta en sessionskänslig kanal.

Undantaget till detta används IDuplexSessionChannel för att både skicka och ta emot meddelanden i ett duplex, sessionskänsligt kommunikationsmönster. Det är möjligt att ena sidan vill sluta skicka meddelanden men fortsätta att ta emot meddelanden, därför när du använder IDuplexSessionChannel det finns en mekanism som gör att du kan stänga utdatasessionen som anger att du inte kommer att skicka fler meddelanden men hålla indatasessionen öppen så att du kan fortsätta att ta emot meddelanden.

I allmänhet stängs sessioner på den utgående sidan och inte på den inkommande sidan. Det innebär att sessionskänsliga utdatakanaler kan stängas och därmed avsluta sessionen på ett rent sätt. Om du stänger en sessionskänslig utdatakanal återgår motsvarande sessionskänsliga indatakanal till programmet som anropar IInputChannel.ReceiveIDuplexSessionChannel.

Sessionskänsliga indatakanaler bör dock inte stängas om inte IInputChannel.ReceiveIDuplexSessionChannel på returnerar null, vilket indikerar att sessionen redan är stängd. Om IInputChannel.Receive den inte har returnerat null kan stängning av IDuplexSessionChannel en sessionskänslig indatakanal utlösa ett undantag eftersom det kan ta emot oväntade meddelanden när den stängs. Om en mottagare vill avsluta en session innan avsändaren gör det bör den anropa Abort indatakanalen, vilket plötsligt avslutar sessionen.

Skriva sessionskänsliga kanaler

Som sessionskänslig kanalförfattare finns det några saker som din kanal måste göra för att tillhandahålla sessioner. På sändningssidan måste kanalen:

  • För varje ny kanal skapar du en ny session och associerar den med ett nytt sessions-ID som är en unik sträng. Eller hämta en ny session från den sessionskänsliga kanalen under dig i stacken.

  • För varje meddelande som skickas med den här kanalen måste du associera meddelandet med sessionen om kanalen skapade sessionen (i stället för att hämta den från lagret under dig). För protokollkanaler görs detta vanligtvis genom att lägga till en SOAP-rubrik. För transportkanaler görs detta vanligtvis genom att skapa en ny transportanslutning eller lägga till sessionsinformation i inramningsprotokollet.

  • För varje meddelande som skickas med den här kanalen måste du ange de leveransgarantier som nämns ovan. Om du förlitar dig på kanalen nedan för att tillhandahålla sessionen ger den kanalen även leveransgarantierna. Om du tillhandahåller sessionen själv måste du implementera dessa garantier som en del av ditt protokoll. Om du i allmänhet skriver en protokollkanal som förutsätter WCF på båda sidor kan du kräva TCP-transporten eller reliable messaging-kanalen och förlita dig på någon av dem för att tillhandahålla en session.

  • När ICommunicationObject.Close anropas på kanalen utför du det arbete som krävs för att stänga sessionen med antingen den angivna tidsgränsen eller standardvärdet. Detta kan vara så enkelt som att anropa Close på kanalen nedanför dig (om du just fått sessionen från den) eller skicka ett särskilt SOAP-meddelande eller stänga en transportanslutning.

  • När Abort anropas på kanalen avslutar du sessionen plötsligt utan att utföra I/O. Det kan innebära att du inte gör något eller att du avbryter en nätverksanslutning eller någon annan resurs.

På mottagarsidan måste kanalen:

  • För varje inkommande meddelande måste kanallyssnaren identifiera den session som den tillhör. Om det här är det första meddelandet i sessionen måste kanallyssnaren skapa en ny kanal och returnera den från anropet till IChannelListener<TChannel>.AcceptChannel. Annars måste kanallyssnaren hitta den befintliga kanal som motsvarar sessionen och leverera meddelandet via kanalen.

  • Om kanalen tillhandahåller sessionen (tillsammans med de nödvändiga leveransgarantierna) kan mottagarsidan behöva utföra vissa åtgärder, till exempel ombeställningsmeddelanden eller skicka bekräftelser.

  • När Close anropas på kanalen utför du det arbete som krävs för att stänga sessionen antingen den angivna tidsgränsen eller standardvärdet. Detta kan resultera i undantag om kanalen tar emot ett meddelande i väntan på att tidsgränsen för stängningen ska upphöra att gälla. Det beror på att kanalen kommer att vara i stängningstillståndet när den tar emot ett meddelande så att den skulle utlösas.

  • När Abort anropas på kanalen avslutar du sessionen plötsligt utan att utföra I/O. Återigen kan det innebära att du inte gör något eller att du avbryter en nätverksanslutning eller någon annan resurs.

Se även