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.

Sex Meddelandeutbytesmönster

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

  • Datagram (IInputChannel och IOutputChannel)

    När du använder ett datagram-MEP skickar en klient ett meddelande med hjälp av en "skicka och glöm" metod. En automatiserad transaktion är en som kräver bekräftelse av leverans via en separat kanal. 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.

  • Request-Response (IRequestChannel och IReplyChannel)

    I denna parlamentsledamot skickas ett meddelande och ett svar tas emot. Mönstret består av begäran-svar-par. 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 klientkanaler IRequestChannel, och tjänstkanaler implementerar IReplyChannel.

  • Duplex (IDuplexChannel)

    Duplex-MEP möjliggör att ett godtyckligt antal meddelanden skickas från en klient och tas emot i vilken ordning som helst. Den duplexa MEP är som ett telefonsamtal, där varje ord som sägs är ett meddelande. Eftersom båda sidor kan skicka och ta emot i denna MEP är det gränssnitt som implementeras av klient- och tjänstkanalerna IDuplexChannel.

Flödesschema som visar de tre grundläggande mönster för meddelandeutbyte
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 (implementeringen av System.ServiceModel.Channels.ISessionChannel<TSession> av 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

Anmärkning

För UDP-transporten är det enda meddelandeutbytet som stöds datagram, eftersom UDP i sig är ett skicka och glöm-protokoll.

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 strukturen för sessionsfulla kanaler längst ned.

Flödesschema som visar strukturen för sessionslösa och sessionskänsliga kanaler

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 är IDuplexSessionChannel som används för att både skicka och ta emot meddelanden i ett duplex, sessionsbaserat 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 kommer den motsvarande sessionskänsliga indatakanalen att returnera 'null' till applikationen som anropar IInputChannel.ReceiveIDuplexSessionChannel.

Sessionfulla indatakanaler bör dock inte stängas, om inte IInputChannel.Receive returnerar null på IDuplexSessionChannel, vilket indikerar att sessionen redan är stängd. Om IInputChannel.ReceiveIDuplexSessionChannel inte har returnerat null kan stängning av en sessionskänslig indatakanal utlösa ett undantag eftersom den 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 sessionshanterande kanaler

Som författare av sessionfulla kanaler 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