Trasporto: Interoperabilità WSE 3.0 TCPTransport: WSE 3.0 TCP Interoperability

L'esempio trasporto: interoperabilità WSE 3.0 TCP illustra come implementare una sessione duplex TCP come un trasporto personalizzato di Windows Communication Foundation (WCF).The WSE 3.0 TCP Interoperability Transport sample demonstrates how to implement a TCP duplex session as a custom Windows Communication Foundation (WCF) transport. Illustra anche come utilizzare l'estendibilità del livello del canale per connettersi via cavo con sistemi distribuiti esistenti.It also demonstrates how you can use the extensibility of the channel layer to interface over the wire with existing deployed systems. La procedura seguente illustra come compilare questo trasporto personalizzato WCF:The following steps show how to build this custom WCF transport:

  1. A partire da un socket TCP, creare client e implementazioni server di IDuplexSessionChannel che utilizzano framing DIME per delineare i limiti del messaggio.Starting with a TCP socket, create client and server implementations of IDuplexSessionChannel that use DIME Framing to delineate message boundaries.

  2. Creare una channel factory che si connette a un servizio TCP WSE e invia messaggi con limiti nelle classi IDuplexSessionChannel del client.Create a channel factory that connects to a WSE TCP service and sends framed messages over the client IDuplexSessionChannels.

  3. Creare un listener del canale per accettare connessioni TCP in ingresso e produrre canali corrispondenti.Create a channel listener to accept incoming TCP connections and produce corresponding channels.

  4. Assicurarsi che eventuali eccezioni specifiche della rete vengano normalizzate nella classe derivata appropriata di CommunicationException.Ensure that any network-specific exceptions are normalized to the appropriate derived class of CommunicationException.

  5. Inserire un elemento di associazione che aggiunge il trasporto personalizzato a uno stack di canali.Add a binding element that adds the custom transport to a channel stack. Per altre informazioni, vedere [aggiunta di un elemento di associazione].For more information, see [Adding a Binding Element].

Creazione di IDuplexSessionChannelCreating IDuplexSessionChannel

Il primo passaggio per scrivere il trasporto interoperabilità WSE 3.0 TCP consiste nel creare un'implementazione di IDuplexSessionChannel su Socket.The first step in writing the WSE 3.0 TCP Interoperability Transport is to create an implementation of IDuplexSessionChannel on top of a Socket. WseTcpDuplexSessionChannel deriva da ChannelBase.WseTcpDuplexSessionChannel derives from ChannelBase. La logica dell'invio di un messaggio è costituita da due parti principali: (1) codifica del messaggio in byte e (2) framing dei byte e invio via cavo.The logic of sending a message consists of two main pieces: (1) Encoding the message into bytes, and (2) framing those bytes and sending them on the wire.

ArraySegment<byte> encodedBytes = EncodeMessage(message);

WriteData(encodedBytes);

Inoltre, viene utilizzato un blocco in modo che le chiamate Send() mantengano la garanzia di ordine di IDuplexSessionChannel e per fare sì che le chiamate al socket sottostante siano sincronizzate correttamente.In addition, a lock is taken so that the Send() calls preserve the IDuplexSessionChannel in-order guarantee, and so that calls to the underlying socket are synchronized correctly.

WseTcpDuplexSessionChannel utilizza una classe MessageEncoder per tradurre classi Message da e verso byte[].WseTcpDuplexSessionChannel uses a MessageEncoder for translating a Message to and from byte[]. Poiché si tratta di un trasporto, WseTcpDuplexSessionChannel è inoltre responsabile dell'applicazione dell'indirizzo remoto con cui il canale è stato configurato.Because it is a transport, WseTcpDuplexSessionChannel is also responsible for applying the remote address that the channel was configured with. EncodeMessage contiene la logica per la conversione.EncodeMessage encapsulates the logic for this conversion.

this.RemoteAddress.ApplyTo(message);

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

Dopo essere stata codificata in byte, la classe Message deve essere trasmessa via cavo.Once the Message is encoded into bytes, it must be transmitted on the wire. Ciò richiede un sistema per la definizione dei limiti del messaggio.This requires a system for defining message boundaries. WSE 3.0 utilizza una versione di DIME come protocollo di framing.WSE 3.0 uses a version of DIME as its framing protocol. WriteData contiene la logica di framing per eseguire il wrapping di un byte[] in un set di record DIME.WriteData encapsulates the framing logic to wrap a byte[] into a set of DIME records.

La logica alla base della ricezione dei messaggi è molto simile.The logic for receiving messages is very similar. Il problema più complesso sta nel gestite il fatto che la lettura di un socket può restituire meno byte di quanto richiesto.The main complexity is handling the fact that a socket read can return less bytes than were requested. Per ricevere un messaggio, WseTcpDuplexSessionChannel legge i byte via cavo, decodifica il framing DIME e utilizza MessageEncoder per tradurre i byte [] in una classe Message.To receive a message, WseTcpDuplexSessionChannel reads bytes off the wire, decodes the DIME framing, and then uses the MessageEncoder for turning the byte[] into a Message.

WseTcpDuplexSessionChannel di base presuppone di ricevere un socket collegato.The base WseTcpDuplexSessionChannel assumes that it receives a connected socket. La classe di base gestisce l'arresto del socket.The base class handles socket shutdown. Ci sono tre posizioni che interfacciano con la chiusura del socket:There are three places that interface with socket closure:

  • OnAbort -- chiude il socket in modo forzato (chiusura forzata).OnAbort -- close the socket ungracefully (hard close).

  • On[Begin]Close -- chiude il socket normalmente (chiusura normale).On[Begin]Close -- close the socket gracefully (soft close).

  • session.CloseOutputSession -- arresta il flusso di dati in uscita (chiusura parziale).session.CloseOutputSession -- shutdown the outbound data stream (half close).

Channel FactoryChannel Factory

Il passaggio successivo per scrivere un trasporto TCP consiste nel creare un'implementazione di IChannelFactory per i canali client.The next step in writing the TCP transport is to create an implementation of IChannelFactory for client channels.

  • WseTcpChannelFactory deriva da ChannelFactoryBase <IDuplexSessionChannel >.WseTcpChannelFactory derives from ChannelFactoryBase<IDuplexSessionChannel>. È una factory che esegue l'override di OnCreateChannel per produrre canali client.It is a factory that overrides OnCreateChannel to produce client channels.

protected override IDuplexSessionChannel OnCreateChannel(EndpointAddress remoteAddress, Uri via)

{

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

}

  • ClientWseTcpDuplexSessionChannel Aggiunge la logica alla base WseTcpDuplexSessionChannel connettersi a un server TCP al channel.Open ora.ClientWseTcpDuplexSessionChannel adds logic to the base WseTcpDuplexSessionChannel to connect to a TCP server at channel.Open time. Il nome host viene innanzitutto risolto in un indirizzo IP, come illustrato nel codice seguente.First the hostname is resolved to an IP address, as shown in the following code.

hostEntry = Dns.GetHostEntry(Via.Host);

  • Il nome host viene quindi connesso al primo indirizzo IP disponibile in un ciclo, come illustrato nel codice seguente.Then the hostname is connected to the first available IP address in a loop, as shown in the following code.

IPAddress address = hostEntry.AddressList[i];

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

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

  • Come parte del contratto del canale, viene eseguito l'incapsulamento delle eccezioni specifiche del dominio, ad esempio SocketException in CommunicationException.As part of the channel contract, any domain-specific exceptions are wrapped, such as SocketException in CommunicationException.

Channel ListenerChannel Listener

Il passaggio successivo per scrivere un trasporto TCP consiste nel creare un'implementazione di IChannelListener per accettare canali server.The next step in writing the TCP transport is to create an implementation of IChannelListener for accepting server channels.

  • WseTcpChannelListener deriva da ChannelListenerBase <IDuplexSessionChannel > e sostituzioni [Begin] Open e On [Begin] Close per controllano la durata del socket di ascolto.WseTcpChannelListener derives from ChannelListenerBase<IDuplexSessionChannel> and overrides On[Begin]Open and On[Begin]Close to control the lifetime of its listen socket. In OnOpen, un socket viene creato per ascoltare su IP_ANY.In OnOpen, a socket is created to listen on IP_ANY. Implementazioni più avanzate possono creare un secondo socket per ascoltare anche su IPv6.More advanced implementations can create a second socket to listen on IPv6 as well. Possono consentire anche che l'indirizzo IP sia specificato nel nome host.They can also allow the IP address to be specified in the hostname.

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);

Quando un nuovo socket viene accettato, viene inizializzato un canale server con esso.When a new socket is accepted, a server channel is initialized with this socket. Tutti gli input e output sono già implementati nella classe di base, pertanto questo canale è responsabile dell'inizializzazione del socket.All the input and output is already implemented in the base class, so this channel is responsible for initializing the socket.

Aggiunta di un elemento di associazione.Adding a Binding Element

Ora che le factory e i canali sono compilati, devono essere esposti al runtime di ServiceModel tramite un'associazione.Now that the factories and channels are built, they must be exposed to the ServiceModel runtime through a binding. Un'associazione è una raccolta di elementi di associazione che rappresentano lo stack di comunicazione associato a un indirizzo del servizio.A binding is a collection of binding elements that represents the communication stack associated with a service address. Ogni elemento dello stack è rappresentato da un elemento di associazione.Each element in the stack is represented by a binding element.

Nell'esempio, l'elemento di associazione è WseTcpTransportBindingElement, che deriva dalla classe TransportBindingElement.In the sample, the binding element is WseTcpTransportBindingElement, which derives from TransportBindingElement. Esso supporta la classe IDuplexSessionChannel ed esegue l'override dei metodi seguenti per compilare le factory associate all'associazione.It supports IDuplexSessionChannel and overrides the following methods to build the factories associated with our binding.

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);

}

Contiene inoltre membri per duplicare BindingElement e restituire lo schema (wse.tcp).It also contains members for cloning the BindingElement and returning our scheme (wse.tcp).

Console per eseguire il test di TCP WSEThe WSE TCP Test Console

Codice per testare l'utilizzo di questo esempio di trasporto è disponibile in TestCode.cs.Test code for using this sample transport is available in TestCode.cs. Nelle istruzioni seguenti viene illustrato come configurare l'esempio TcpSyncStockService WSE.The following instructions show how to set up the WSE TcpSyncStockService sample.

Il codice di prova crea un'associazione personalizzata che utilizza MTOM come codifica e WseTcpTransport come trasporto.The test code creates a custom binding that uses MTOM as the encoding and WseTcpTransport as the transport. Configura inoltre la versione di indirizzamento in modo che sia conforme a WSE 3.0, come illustrato nel codice seguente.It also sets up the AddressingVersion to be conformant with WSE 3.0, as shown in the following code.

CustomBinding binding = new CustomBinding();

MtomMessageEncodingBindingElement mtomBindingElement = new MtomMessageEncodingBindingElement();

mtomBindingElement.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;

binding.Elements.Add(mtomBindingElement);

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

È costituito da due test. Il primo imposta un client tipizzato utilizzando codice generato da WSE 3.0 WSDL.It consists of two tests—one test sets up a typed client using code generated from the WSE 3.0 WSDL. Il secondo test utilizza WCF come sia il client e server inviando direttamente messaggi sul canale API.The second test uses WCF as both the client and the server by sending messages directly on top of the channel APIs.

Quando si esegue l'esempio, viene visualizzato l'output seguente:When running the sample, the following output is expected.

Client:Client:

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.  

Server:Server:

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  

Per impostare, compilare ed eseguire l'esempioTo set up, build, and run the sample

  1. Per eseguire l'esempio è necessario avere installato WSE 3.0 e l'esempio TcpSyncStockService WSE.To run this sample, you must have WSE 3.0 and the WSE TcpSyncStockService sample installed. È possibile scaricare WSE 3.0 da MSDN.You can download WSE 3.0 from MSDN.

Nota

Poiché WSE 3.0 non è supportato su Windows Server 2008Windows Server 2008, non è possibile installare o eseguire l'esempio TcpSyncStockService in tale sistema operativo.Because WSE 3.0 is not supported on Windows Server 2008Windows Server 2008, you cannot install or run the TcpSyncStockService sample on that operating system.

  1. Dopo aver installato l'esempio TcpSyncStockService, eseguire le operazioni seguenti:Once you install the TcpSyncStockService sample, do the following:

    1. Aprire TcpSyncStockService in Visual Studio (si noti che l'esempio TcpSyncStockService viene installato con WSE 3.0Open the TcpSyncStockService in Visual Studio (Note that the TcpSyncStockService sample is installed with WSE 3.0. e non fa parte del codice di questo esempio).It is not part of this sample's code).

    2. Impostare StockService come progetto di avvio.Set the StockService project as the start up project.

    3. Aprire StockService.cs nel progetto StockService e impostare come commento l'attributo [Policy] sulla classe StockService.Open StockService.cs in the StockService project and comment out the [Policy] attribute on the StockService class. Ciò disabilita la sicurezza dell'esempio.This disables security from the sample. Sebbene WCF può interagire con WSE 3.0 endpoint sicuri, la sicurezza è disabilitata per mantenere l'esempio sia focalizzato sul trasporto TCP personalizzato.While WCF can interoperate with WSE 3.0 secure endpoints, security is disabled to keep this sample focused on the custom TCP transport.

    4. Premere F5 per avviare TcpSyncStockService.Press F5 to start the TcpSyncStockService. Il servizio si avvia in una nuova finestra della console.The service starts in a new console window.

    5. Aprire questo esempio di trasporto TCP in Visual Studio.Open this TCP transport sample in Visual Studio.

    6. Aggiornare la variabile "nome host" in TestCode.cs e farla corrispondere al nome del computer che esegue TcpSyncStockService.Update the "hostname" variable in TestCode.cs to match the machine name running the TcpSyncStockService.

    7. Premere F5 per avviare l'esempio Trasporto TCP.Press F5 to start the TCP transport sample.

    8. Il client di prova del trasporto TCP viene inizializzato in una nuova console.The TCP transport test client starts in a new console. Il client richiede quotazioni al servizio e quindi visualizza i risultati nella finestra della console.The client requests stock quotes from the service and then displays the results in its console window.

Vedere ancheSee Also