Udostępnij za pośrednictwem


Transport: Współdziałanie protokołu TCP WSE 3.0

Przykład transportu współoperacyjnego TCP w WSE 3.0 demonstruje, jak zaimplementować sesję dwukierunkową TCP jako niestandardowy transport w Windows Communication Foundation (WCF). Pokazuje również, jak można wykorzystać rozszerzalność warstwy kanału do interfejsowania przez przewód z istniejącymi wdrożonymi systemami. W poniższych krokach pokazano, jak utworzyć ten niestandardowy transport WCF:

  1. Począwszy od gniazda TCP, utwórz implementacje IDuplexSessionChannel klienta i serwera, które używają framingu DIME, aby oddzielić granice komunikatów.

  2. Utwórz fabrykę kanałów, która łączy się z usługą TCP WSE i wysyła komunikaty framowane za pośrednictwem klientów IDuplexSessionChannel.

  3. Utwórz odbiornik kanału w celu akceptowania przychodzących połączeń TCP i tworzenia odpowiednich kanałów.

  4. Upewnij się, że wszystkie wyjątki specyficzne dla sieci są znormalizowane do odpowiedniej klasy pochodnej klasy CommunicationException.

  5. Dodaj element powiązania, który dodaje niestandardowy transport do stosu kanału. Aby uzyskać więcej informacji, zobacz [Dodawanie elementu powiązania].

Tworzenie IDuplexSessionChannel

Pierwszym krokiem w procesie tworzenia WSE 3.0 TCP Interoperability Transport jest utworzenie implementacji IDuplexSessionChannel na Socket. WseTcpDuplexSessionChannel pochodzi od ChannelBase. Logika wysyłania komunikatu składa się z dwóch głównych elementów: (1) kodowania komunikatu w bajtach i (2) ramowania tych bajtów i ich transmisji siecią.

ArraySegment<byte> encodedBytes = EncodeMessage(message);

WriteData(encodedBytes);

Ponadto zakładana jest blokada, aby wywołania Send() utrzymały gwarancję IDuplexSessionChannel dotyczącą kolejności oraz aby wywołania do bazowego gniazda były prawidłowo zsynchronizowane.

WseTcpDuplexSessionChannel używa elementu MessageEncoder do tłumaczenia elementu Message do i z bajtu[]. Ponieważ jest to transport, WseTcpDuplexSessionChannel jest również odpowiedzialny za zastosowanie zdalnego adresu, którym skonfigurowano kanał. EncodeMessage zawiera logikę konwersji.

this.RemoteAddress.ApplyTo(message);

return encoder.WriteMessage(message, maxBufferSize, bufferManager);

Po zakodowaniu Message w bajtach należy go przekazać w przewodzie. Wymaga to systemu do definiowania granic komunikatów. WSE 3.0 używa wersji DIME jako protokołu framingu. WriteData Hermetyzuje logikę tworzenia ramek w celu zawijania bajtu[] do zestawu rekordów DIME.

Logika odbierania komunikatów jest podobna. Główną złożonością jest obsługa faktu, że odczyt gniazda może zwrócić mniej bajtów niż zażądano. Aby odebrać komunikat, WseTcpDuplexSessionChannel odczytuje bajty z przewodu, dekoduje ramkę DIME, a następnie używa MessageEncoder elementu do przekształcania bajtu[] w Message.

W bazie WseTcpDuplexSessionChannel przyjęto założenie, że otrzymuje połączone gniazdo. Klasa bazowa obsługuje zamykanie gniazd. Istnieją trzy miejsca, które interagują z procesem zamknięcia gniazda.

  • OnAbort - zamknij gniazdo niegrzecznie (twarde zamknięcie).

  • Na[Początek]Zamknij - zamknij gniazdo bezpiecznie (miękkie zamknięcie).

  • sesja.CloseOutputSession — zamknij strumień danych wychodzących (częściowe zamknięcie).

Fabryka kanałów

Następnym krokiem podczas pisania transportu TCP jest utworzenie implementacji IChannelFactory dla kanałów klienckich.

  • WseTcpChannelFactory pochodzi z ChannelFactoryBase<IDuplexSessionChannel>. Jest to fabryka, która zastępuje OnCreateChannel tworzenie kanałów klienckich.

protected override IDuplexSessionChannel OnCreateChannel(EndpointAddress remoteAddress, Uri via)

{

return new ClientWseTcpDuplexSessionChannel(encoderFactory, bufferManager, remoteAddress, via, this);

}

  • ClientWseTcpDuplexSessionChannel dodaje logikę do bazy WseTcpDuplexSessionChannel w celu nawiązania połączenia z serwerem TCP w channel.Open czasie. Najpierw nazwa hosta jest rozpoznawana jako adres IP, jak pokazano w poniższym kodzie.

hostEntry = Dns.GetHostEntry(Via.Host);

  • Następnie nazwa hosta jest połączona z pierwszym dostępnym adresem IP w pętli, jak pokazano w poniższym kodzie.

IPAddress address = hostEntry.AddressList[i];

socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

socket.Connect(new IPEndPoint(address, port));

  • W ramach umowy dotyczącej kanału, wszystkie wyjątki specyficzne dla domeny są opakowane, takie jak SocketException w CommunicationException.

Odbiornik kanału

Następnym krokiem podczas pisania transportu TCP jest utworzenie implementacji akceptowania IChannelListener kanałów serwera.

  • WseTcpChannelListener pochodzi z ChannelListenerBase<IDuplexSessionChannel> i zastępuje on[Begin]Open i On[Begin]Close, aby kontrolować okres istnienia gniazda nasłuchiwania. W funkcji OnOpen jest tworzone gniazdo do nasłuchiwania na IP_ANY. Bardziej zaawansowane implementacje mogą również utworzyć drugie gniazdo do nasłuchiwania przy użyciu protokołu IPv6. Mogą również zezwalać na określenie adresu IP w nazwie hosta.

IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, uri.Port);

this.listenSocket = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

this.listenSocket.Bind(localEndpoint);

this.listenSocket.Listen(10);

Po zaakceptowaniu nowego gniazda kanał serwera jest inicjowany za pomocą tego gniazda. Wszystkie dane wejściowe i wyjściowe są już implementowane w klasie bazowej, więc ten kanał jest odpowiedzialny za inicjowanie gniazda.

Dodawanie elementu powiązania

Teraz, gdy fabryki i kanały zostały zbudowane, muszą być udostępnione w środowisku uruchomieniowym ServiceModel za pomocą powiązania. Powiązanie to kolekcja elementów powiązania, które reprezentują stos komunikacji skojarzony z adresem usługi. Każdy element w stosie jest reprezentowany przez element powiązania.

W przykładzie element powiązania to WseTcpTransportBindingElement, który pochodzi z elementu TransportBindingElement. Obsługuje IDuplexSessionChannel i zastępuje następujące metody, aby tworzyć fabryki związane z naszym wiązaniem.

public IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)

{

return (IChannelFactory<TChannel>)(object)new WseTcpChannelFactory(this, context);

}

public IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)

{

return (IChannelListener<TChannel>)(object)new WseTcpChannelListener(this, context);

}

Zawiera również elementy członkowskie do klonowania BindingElement i zwracania naszego schematu (wse.tcp).

Konsola testowa PROTOKOŁU TCP programu WSE

Kod testowy do korzystania z tego przykładowego transportu jest dostępny w TestCode.cs. Poniższe instrukcje pokazują, jak przygotować przykładową konfigurację WSE TcpSyncStockService.

Kod testowy tworzy niestandardowe powiązanie, które używa MTOM jako kodowania oraz WseTcpTransport jako transportu. Konfiguruje również wersję AddressingVersion zgodnie z WSE 3.0, jak pokazano w poniższym kodzie.

CustomBinding binding = new CustomBinding();

MtomMessageEncodingBindingElement mtomBindingElement = new MtomMessageEncodingBindingElement();

mtomBindingElement.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;

binding.Elements.Add(mtomBindingElement);

binding.Elements.Add(new WseTcpTransportBindingElement());

Składa się z dwóch testów — jeden test konfiguruje typizowanego klienta przy użyciu kodu wygenerowanego na podstawie WSDL programu WSE 3.0. Drugi test używa WCF zarówno jako klienta, jak i serwera, wysyłając komunikaty bezpośrednio nad interfejsami API kanału.

Podczas uruchamiania przykładu oczekiwane są następujące dane wyjściowe.

Klient:

Calling soap://stockservice.contoso.com/wse/samples/2003/06/TcpSyncStockService

Symbol: FABRIKAM
        Name: Fabrikam, Inc.
        Last Price: 120

Symbol: CONTOSO
        Name: Contoso Corp.
        Last Price: 50.07
Press enter.

Received Action: http://SayHello
Received Body: to you.
Hello to you.
Press enter.

Received Action: http://NotHello
Received Body: to me.
Press enter.

Serwer:

Listening for messages at soap://stockservice.contoso.com/wse/samples/2003/06/TcpSyncStockService

Press any key to exit when done...

Request received.
Symbols:
        FABRIKAM
        CONTOSO

Konfigurowanie, kompilowanie i uruchamianie przykładu

  1. Aby uruchomić ten przykład, musisz mieć zainstalowane ulepszenia usług sieci Web (WSE) 3.0 dla platformy Microsoft .NET i przykład programu WSE TcpSyncStockService .

Uwaga / Notatka

Ponieważ program WSE 3.0 nie jest obsługiwany w systemie Windows Server 2008, nie można zainstalować ani uruchomić przykładu TcpSyncStockService w tym systemie operacyjnym.

  1. Po zainstalowaniu przykładu TcpSyncStockService wykonaj następujące czynności:

    1. Otwórz TcpSyncStockService w programie Visual Studio. ( Przykład TcpSyncStockService jest instalowany z programem WSE 3.0. Nie jest częścią kodu tego przykładu).

    2. Ustaw projekt StockService jako projekt startowy.

    3. Otwórz StockService.cs w projekcie StockService i oznacz jako komentarz atrybut [Policy] w StockService klasie. Spowoduje to wyłączenie zabezpieczeń z przykładu. Chociaż program WCF może współpracować z bezpiecznymi punktami końcowymi programu WSE 3.0, zabezpieczenia są wyłączone, aby zachować ten przykład skoncentrowany na niestandardowym transporcie TCP.

    4. naciśnij F5, aby uruchomić TcpSyncStockService. Usługa jest uruchamiana w nowym oknie konsoli.

    5. Otwórz ten przykład transportu TCP w programie Visual Studio.

    6. Zaktualizuj zmienną "hostname" w TestCode.cs, aby odpowiadała nazwie komputera uruchamiającego TcpSyncStockService.

    7. naciśnij F5 , aby uruchomić przykład transportu TCP.

    8. Klient testowy transportu TCP jest uruchamiany w nowej konsoli. Klient żąda ofert giełdowych z usługi, a następnie wyświetla wyniki w oknie konsoli.