Wybieranie platformy wymiany komunikatów

Pierwszym krokiem w pisaniu transportu niestandardowego jest podjęcie decyzji, które wzorce wymiany komunikatów (lub deputowanych) są wymagane dla opracowywanego kanału. W tym temacie opisano dostępne opcje i omówiono różne wymagania. Jest to pierwsze zadanie na liście zadań tworzenia kanału opisane w temacie Tworzenie kanałów.

Sześć wzorców wymiany komunikatów

Spośród trzech posłów do PE należy wybrać:

  • Datagram (IInputChannel i IOutputChannel)

    W przypadku korzystania z datagramu MEP klient wysyła komunikat przy użyciu ognia i zapomnij wymiany. Ogień i zapominanie wymiany jest taki, który wymaga potwierdzenia poza pasmem pomyślnego dostarczenia. Wiadomość może zostać utracona podczas przesyłania i nigdy nie dociera do usługi. Jeśli operacja wysyłania zakończy się pomyślnie na końcu klienta, nie gwarantuje, że zdalny punkt końcowy odebrał komunikat. Datagram jest podstawowym blokiem konstrukcyjnym do obsługi komunikatów, ponieważ można tworzyć własne protokoły, w tym niezawodne protokoły i bezpieczne protokoły. Kanały datagramu klienta implementują IOutputChannel interfejs i kanały datagramu usługi implementują IInputChannel interfejs.

  • Request-Response (IRequestChannel i IReplyChannel)

    W tym mepcie zostanie wysłana wiadomość i otrzymana jest odpowiedź. Wzorzec składa się z par żądań-odpowiedzi. Przykłady wywołań żądań odpowiedzi to zdalne wywołania procedur (RPC) i żądania GET przeglądarki. Ten wzorzec jest również nazywany półdupleksem. W tym mepcie kanały klienta implementują IRequestChannel i implementują IReplyChannelkanały usług .

  • Dupleks (IDuplexChannel)

    Dupleksowy poseł DO PE umożliwia dowolną liczbę komunikatów wysyłanych przez klienta i odbieranych w dowolnej kolejności. Dwudupleksowy poseł do PE jest jak rozmowa telefoniczna, gdzie każde słowo mówione jest wiadomością. Ponieważ obie strony mogą wysyłać i odbierać w tym mepcie, interfejs implementowany przez klienta i kanały usług to IDuplexChannel.

Flowchart showing the three basic message exchange patterns
Trzy podstawowe wzorce wymiany komunikatów. Góra do dołu: datagram, żądanie-odpowiedź i dupleks.

Każdy z tych posłów może również wspierać sesje. Sesja (i implementacja System.ServiceModel.Channels.ISessionChannel<TSession> typu System.ServiceModel.Channels.ISession) koreluje wszystkie komunikaty wysyłane i odbierane w kanale. Wzorzec odpowiedzi na żądanie jest autonomiczną sesją z dwoma komunikatami, ponieważ żądanie i odpowiedź są skorelowane. Z kolei wzorzec żądania-odpowiedzi, który obsługuje sesje, oznacza, że wszystkie pary żądań/odpowiedzi w tym kanale są skorelowane ze sobą. Daje to w sumie sześciu posłów do parlamentu do wyboru:

  • Datagram

  • Żądanie-odpowiedź

  • Dupleks

  • Datagram z sesjami

  • Żądanie odpowiedzi z sesjami

  • Dupleks z sesjami

Uwaga

W przypadku transportu UDP jedynym obsługiwanym deputowanym jest datagram, ponieważ UDP jest z natury pożarem i zapomnij protokołu.

Sesje i kanały sesji

W świecie sieci istnieją protokoły zorientowane na połączenie (na przykład TCP) i protokoły bez połączenia (na przykład UDP). WCF używa terminu sesji, aby oznaczać abstrakcję logiczną podobną do połączenia. Sesjowe protokoły WCF są podobne do protokołów sieciowych zorientowanych na połączenie, a protokoły WCF bez sesji są podobne do protokołów sieciowych bez połączenia.

W modelu obiektów kanału każda sesja logiczna manifestuje się jako wystąpienie kanału sesji. W związku z tym każda nowa sesja utworzona przez klienta i zaakceptowana w usłudze odpowiada nowemu kanałowi sesji po każdej stronie. Na poniższym diagramie przedstawiono strukturę kanałów bez sesji i u dołu strukturę kanałów sesji.

Flowchart showing the structure of sessionless and sessionful channels

Klient tworzy nowy kanał sesji i wysyła komunikat. Po stronie usługi odbiornik kanału odbiera ten komunikat i wykrywa, że należy do nowej sesji, aby utworzyć nowy kanał sesji i przekazać go do aplikacji (w odpowiedzi na aplikację wywołującą AcceptChannel na odbiorniku kanału). Następnie aplikacja odbiera ten komunikat i wszystkie kolejne komunikaty wysyłane w tej samej sesji za pośrednictwem tego samego kanału sesji.

Inny klient (lub ten sam klient) tworzy nową sesję i wysyła komunikat. Odbiornik kanału wykrywa ten komunikat w nowej sesji i tworzy nowy kanał sesji, a proces powtarza się.

Bez sesji nie ma korelacji między kanałami i sesjami. W związku z tym odbiornik kanału tworzy tylko jeden kanał, za pośrednictwem którego wszystkie odebrane komunikaty są dostarczane do aplikacji. Nie ma również kolejności komunikatów, ponieważ nie ma sesji, w ramach której należy zachować kolejność komunikatów. Górna część powyższej grafiki ilustruje wymianę komunikatów bez sesji.

Uruchamianie i kończenie sesji

Sesje są uruchamiane na kliencie, po prostu tworząc nowy kanał sesji. Są one uruchamiane w usłudze, gdy usługa odbiera komunikat, który został wysłany w nowej sesji. Podobnie sesje są przerywane przez zamknięcie lub przerwanie kanału sesji.

Wyjątek jest używany IDuplexSessionChannel zarówno do wysyłania i odbierania komunikatów we wzorcu komunikacji dwudupleksowej, sesji. Istnieje możliwość, że jedna strona będzie chciała przestać wysyłać komunikaty, ale nadal odbierać komunikaty, dlatego w przypadku korzystania z IDuplexSessionChannel mechanizmu, który umożliwia zamknięcie sesji wyjściowej wskazującej, że nie będzie wysyłać więcej komunikatów, ale zachować otwartą sesję wejściową, umożliwiając kontynuowanie odbierania komunikatów.

Ogólnie rzecz biorąc, sesje są zamykane po stronie wychodzącej, a nie po stronie przychodzącej. Oznacza to, że kanały wyjściowe sesji można zamknąć, co pozwala na czyste zakończenie sesji. Zamknięcie sesji kanału wyjściowego powoduje, że odpowiedni kanał wejściowy sesji zwraca wartość null do aplikacji wywołującej IInputChannel.ReceiveIDuplexSessionChannelelement .

Jednak kanały wejściowe sesji nie powinny być zamykane, chyba że IInputChannel.Receive w zwracaniu IDuplexSessionChannel wartości null, co oznacza, że sesja jest już zamknięta. Jeśli IInputChannel.Receive na obiekcie IDuplexSessionChannel nie zwrócono wartości null, zamknięcie sesji kanału wejściowego może zgłosić wyjątek, ponieważ może odbierać nieoczekiwane komunikaty podczas zamykania. Jeśli odbiorca chce zakończyć sesję przed wykonaniem przez nadawcę, powinien wywołać Abort kanał wejściowy, który nagle kończy sesję.

Pisanie kanałów sesji

Jako autor kanału sesji istnieje kilka rzeczy, które kanał musi wykonać, aby zapewnić sesje. Po stronie wysyłania kanał musi:

  • Dla każdego nowego kanału utwórz nową sesję i skojarz ją z nowym identyfikatorem sesji, który jest unikatowym ciągiem. Możesz też uzyskać nową sesję z kanału sesji poniżej ciebie w stosie.

  • Dla każdego komunikatu wysyłanego przy użyciu tego kanału, jeśli kanał utworzył sesję (w przeciwieństwie do uzyskania go z poniższej warstwy), musisz skojarzyć komunikat z sesją. W przypadku kanałów protokołu zazwyczaj odbywa się to przez dodanie nagłówka PROTOKOŁU SOAP. W przypadku kanałów transportowych zazwyczaj odbywa się to przez utworzenie nowego połączenia transportowego lub dodanie informacji o sesji do protokołu framingu.

  • Dla każdego komunikatu wysyłanego przy użyciu tego kanału należy podać gwarancje dostarczania wymienione powyżej. Jeśli korzystasz z kanału poniżej, aby podać sesję, ten kanał zapewni również gwarancje dostarczania. Jeśli udostępniasz sesję samodzielnie, musisz zaimplementować te gwarancje w ramach protokołu. Ogólnie rzecz biorąc, jeśli piszesz kanał protokołu, który zakłada, że program WCF po obu stronach może wymagać transportu TCP lub kanału Reliable Messaging i polegać na jednym, aby zapewnić sesję.

  • Po ICommunicationObject.Close wywołaniu w kanale wykonaj pracę niezbędną do zamknięcia sesji przy użyciu określonego limitu czasu lub domyślnego. Może to być tak proste, jak wywołanie Close w kanale poniżej (jeśli właśnie uzyskano z niej sesję) lub wysłanie specjalnej wiadomości SOAP lub zamknięcie połączenia transportowego.

  • Po Abort wywołaniu kanału zakończ sesję nagle bez wykonywania operacji we/wy. Może to oznaczać, że nic nie robi lub może wymagać przerwania połączenia sieciowego lub innego zasobu.

Po stronie odbierania kanał musi:

  • Dla każdego przychodzącego komunikatu odbiornik kanału musi wykryć sesję, do którego należy. Jeśli jest to pierwszy komunikat w sesji, odbiornik kanału musi utworzyć nowy kanał i zwrócić go z wywołania do IChannelListener<TChannel>.AcceptChannel. W przeciwnym razie odbiornik kanału musi znaleźć istniejący kanał odpowiadający sesji i dostarczyć komunikat za pośrednictwem tego kanału.

  • Jeśli twój kanał udostępnia sesję (wraz z wymaganymi gwarancjami dostarczania), strona odbierania może być wymagana do wykonania niektórych akcji, takich jak ponowne zamawianie komunikatów lub wysyłanie potwierdzeń.

  • Po Close wywołaniu kanału należy wykonać pracę niezbędną do zamknięcia sesji albo określonego limitu czasu lub domyślnego. Może to spowodować wyjątki, jeśli kanał odbierze komunikat podczas oczekiwania na wygaśnięcie limitu czasu zamknięcia. Dzieje się tak, ponieważ kanał będzie w stanie Zamykanie po odebraniu komunikatu, aby został zgłoszony.

  • Po Abort wywołaniu kanału zakończ sesję nagle bez wykonywania operacji we/wy. Ponownie może to oznaczać, że nic nie robi lub może wymagać przerwania połączenia sieciowego lub innego zasobu.

Zobacz też