2010-10-27 7 views
9

Uhm, sto assolutamente perso in modo che qualsiasi aiuto sarebbe molto apprezzatoIn che modo nel sistema duplex WCF si differenzia tra le diverse istanze del canale?

Il OperationContext.Current.InstanceContext è il contesto della corrente istanza di servizio che il canale in arrivo è utilizzando.

In un sistema duplex, il servizio può richiamare nel client tramite un CallbackContract . Questo CallbackControl è molto simile a un servizio sul lato client che è in ascolto per le chiamate dal servizio sul canale che il client ha aperto . Questo "servizio di callback client " è accessibile solo tramite lo stesso canale utilizzato nel servizio e pertanto solo il servizio ha accesso a .

a) Quindi nei sistemi duplex la stessa istanza di canale con cui il lato client invia messaggi al servizio, viene utilizzata anche dal client per ricevere messaggi dal servizio?

b) Se nel sistema di richiesta-risposta un client utilizza un'istanza di canale specifica clientChannel per inviare un messaggio al servizio, quindi suppongo che questa stessa istanza (quindi clientChannel) debba rimanere aperta finché il servizio non restituisce una risposta a questa istanza , mentre nel sistema duplex clientChannel deve rimanere aperto fino alla chiusura della sessione?

c) Sto assumendo un comportamento del genere poiché, per quanto posso dire, ogni istanza di canale ha un indirizzo univoco (o ID) che aiuta a differenziarlo da altre istanze di canale) in esecuzione sullo stesso client? E quando il servizio rimanda un messaggio, specifica anche un ID di questo canale?

Così, quando nel client di sistema Duplex si chiama un servizio, WCF crea (sul lato client) un'istanza di canale clientChannel, che invia un messaggio sul filo. Sul lato server, WCF crea l'istanza del canale serverChannel, che consegna il messaggio all'operazione richiesta (metodo). Quando questo metodo richiede la richiamata al client tramite CallbackContract, utilizza InstanceContext.GetCallBackChannel<> per creare un canale, che tra le altre cose contiene l'ID del canale che ha chiamato un servizio (quindi contiene un indirizzo esatto o ID di clientChannel)?

d) Nei client duplex il client utilizza la stessa istanza del canale per chiamare qualsiasi delle operazioni dell'endpoint?

Grazie

+0

Ho letto qualcosa che chiarisce un po ', ma lascia ancora delle risposte sul voodoo dei doppi collegamenti: i protocolli di trasporto TCP e Named Pipes supportano implicitamente i callback. Possono sempre tornare dal cliente. Per HTTP, DuplexClientBase gestisce la creazione dell'endpoint client ospitando un servizio sul client e ascoltando un indirizzo http temporaneo sulla porta 80 per i messaggi dal servizio. – Trevor

risposta

6

Non sono sicuro, ma ecco come ho capito questo per una comunicazione in modalità duplex.

Ho dato un'occhiata alla classe InstanceContext definita nell'assembly System.ServiceModel usando decompiler dotPeek.

Internamente c'è una chiamata

this.channels = new ServiceChannelManager(this); 

Ciò significa, sta generando canale utilizzando un ServiceChannelManager passando l'istanza dello stesso InstanceContext. In questo modo mantiene una traccia del Canale con l'istanza di InstanceContext.

Poi si lega è il canale in entrata (servizio a cliente) le richieste di metodo che viene implementato come:

internal void BindIncomingChannel(ServiceChannel channel) 
    { 
     this.ThrowIfDisposed(); 
     channel.InstanceContext = this; 
     IChannel channel1 = (IChannel) channel.Proxy; 
     this.channels.AddIncomingChannel(channel1); 
     if (channel1 == null) 
     return; 
     switch (channel.State) 
     { 
     case CommunicationState.Closing: 
     case CommunicationState.Closed: 
     case CommunicationState.Faulted: 
      this.channels.RemoveChannel(channel1); 
      break; 
     } 
    } 

Quindi, per rispondere alle vostre domande:

a. Sì, mantiene internamente le relazioni Servizio e InstanceContext (che crea un canale) per le chiamate tra Client e Servizio.

b. Sì, il canale deve rimanere aperto fino a quando il Servizio non risponde al contesto, in cui l'InstanceContext si occuperà della chiusura del canale.

c. Ogni client ha un ID sessione univoco, ma il tipo InstanceContext nel servizio dipende da InstanceContextMode utilizzato nel servizio per l'implementazione del contratto.

d. Usa lo stesso canale. InstanceContext mantiene il conteggio dei canali IncomingChannel e Outgoing. I canali in entrata sono quelli che sono diretti al cliente dal servizio al cliente e quelli in uscita sono diretti al cliente. Puoi vedere questo conteggio usando debugger in VS.

Per motivi di ulteriori chiarimenti, per quanto riguarda l'altro comportamento per un servizio duplex è interessato, ecco come possiamo osservare il comportamento di InstanceContext e come canale di istanza viene creata:

ho creato un duplex servizio di demo:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceDuplexCallback))] 
public interface IServiceClass 
{ 
    [OperationContract(IsOneWay = true)] 
    void Add(int num1); 
} 

il presente contratto è implementato come:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
public class ServiceClass : IServiceClass 
{ 
    int result = 0; 

    public void Add(int num1) 
    { 
     result += num1; 
     callBack.Calculate(result); 
    } 

    IServiceDuplexCallback callBack 
    { 
     get 
     { 
      return OperationContext.Current.GetCallbackChannel<IServiceDuplexCallback>(); 
     } 
    } 
} 

In questa implementazione notare la prima linea dove InstanceConte xtMode è impostato su PerCall. L'impostazione predefinita è PerSession.

Questa enumerazione ha tre opzioni:

  1. PerCall - Nuova istanza di InstanceContext utilizzato per ogni chiamata indipendente sessione

  2. PerSession - Nuova istanza utilizzata per ogni sessione

  3. singolo - Una singola istanza di InstanceContext utilizzata per tutti i client.

ho creato un client che utilizzano NetTcpBinding di connettersi con Service:

InstanceContext ic = new InstanceContext(new TCPCallbackHandler(ref textBox1)); 
TCP.ServiceClassClient client = new TCP.ServiceClassClient(ic); 

// First call to Add method of the Contract 
client.Add(val1); 
// Second call to Add method of the Contract 
client.Add(val2); 

TCPCallbackHandler è la classe nel client che implementa il contratto di richiamata come:

public class TCPCallbackHandler : TCP.IServiceClassCallback 
{ 
    TextBox t; 

    public TCPCallbackHandler(ref TextBox t1) 
    { 
     t = t1; 
    } 

    public void Calculate(int result) 
    { 
     t.Text += OperationContext.Current.SessionId + " " + result.ToString(); 
    } 
} 

Per vedere la comportamento di InstanceContext, ho avviato il servizio e quindi ho avviato due client con ciascuna operazione di enumerazione come discusso sopra.Ecco i risultati:

1 - PerCall

client 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 - urn: uuid: 4c5f3d8b-9203-4f25-b09a- 839089ecbe54

client 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 - urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01

qui - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 è SessionId

Dato che per ogni cliente aggiungere è chiamato due volte nel client, e in PerCall -> nuova istanza di InstanceContext viene creato ogni chiamata , creiamo una nuova istanza di ServiceClass per entrambe le chiamate di ogni client. Punto da notare qui è che la nuova istanza viene creato anche per la stessa sessione

// prima chiamata al metodo Add del Contratto

client.Add (val1); -> nuova istanza di ServiceClass creato e il valore viene incrementato di 5

// Seconda chiamata per aggiungere il metodo del contratto

client.Add (val2); -> nuova istanza di ServiceClass creato e il valore viene incrementato di 5

2 - PerSession

client 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 - urna : uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54

client 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 - urn: uuid: e101d2a7-ae41-4929-9789 -6d43abf97f01

Qui l'istanza di ServiceClass è separata per entrambi il client poiché hanno sessioni diverse in esecuzione. Quindi, l'incremento delle chiamate è 0 -> 5 -> 10 (sia per il cliente separatamente)

3 - Single

client 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54

client 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 - urn: uuid: e101d2a7- ae41-4929-9789-6d43abf97f01

Qui la stessa istanza di ServiceClass è condivisa da tutti i client, quindi abbiamo 0 -> 5 -> 10 nel primo client. Il secondo client incrementerà nella stessa istanza, quindi otteniamo 10 -> 15 -> 20.

Questo si comporta in modo diverso a seconda della chiamata e può dare risultati come quando invocato allo stesso tempo dai client.

client 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54

client 2: urn: uuid : e101d2a7-ae41-4929-9789-6d43abf97f01 - urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01

Spero che questo aiuti!

Problemi correlati