2009-11-01 8 views
5

mi sono imbattuto in un eccezione Remoting:Remoting e canale mancante affonda

"Questo proxy comunicazione remota non ha sink di canale che significa che sia il server non ha canali server registrato in ascolto, o questa applicazione non ha alcun canale client adatto per parlare con il server. "

La causa è meglio spiegato da this blog entry ho trovato:

Il secondo caso è più oscura. Questo si verifica quando il client effettua una chiamata al server, il server restituisce un riferimento oggetto e il client quindi effettua una chiamata sull'oggetto di riferimento sul server. Se l'oggetto di riferimento si trova in un AppDomain secondario su il server, l'eccezione sopra può essere generata da . Se il problema si verifica è perché la registrazione del canale solo si applica all'AppDomain in cui viene chiamato RegisterChannel e non è stato registrato alcun canale nell'AppDomain secondario secondario. Il riferimento all'oggetto restituito al client punti all'oggetto in AppDomain secondario, non al suo proxy nel AppDomain primario , e quindi non c'è canale tra il client e il dominio di applicazione secondario attraverso il quale la chiamata può passaggio. Soluzione: registrare un canale nell'AppDomain secondario in in cui è presente l'oggetto di riferimento.

Questo corrisponde al mio scenario poiché ho un servizio che carica i plugin in appdomain separati. Le istanze dell'oggetto (implementazioni di un'interfaccia definita in un assembly a cui fanno riferimento tutti gli assembly) vengono create negli appdomain secondari e fanno riferimento al servizio (cross-appdomain, quindi il servizio ha riferimenti proxy). Il servizio restituisce quindi questi riferimenti proxy a un'applicazione. Esistono canali registrati tra l'applicazione e il servizio, ma nulla tra il plugin e l'applicazione.

Ho pensato che un proxy sarebbe stato sufficiente per superare i limiti dell'appodominio. Devo davvero creare canali tra i plugin e l'applicazione? Non sembra affatto giusto, quindi mi mancherà qualcosa.

risposta

2

Per utilizzare i servizi remoti tra gli appdomain su oggetti derivati ​​da MarshalByRefObject è necessario creare canali su entrambe le estremità. Pertanto, è necessario creare canali in ogni appdomain. Esistono canali efficienti per farlo localmente sulla stessa macchina, ad es. il canale IPC (usa named pipe).

Se la comunicazione è "a senso unico", nel senso che solo uno dei lati chiama i metodi sui proxy, si registra qui un canale client e il canale server sul lato che crea gli oggetti.

Nel caso in cui sia necessario andare in entrambe le direzioni, ad es.passare un oggetto di registrazione per il "server" al fine di ricevere un feedback log continuo, è necessario registrare un canale del server ad entrambe le estremità, come il client improvvisamente serve anche oggetti:

class MyLogger : MarshalByRefObject 
{ 
    public Log(string text) { ... } 
} 

MyLogger logger = new MyLogger(); 
proxyObj.LongRunningCommand(logger); 
3

Ad ampliare @ di RonCohen risposta -

sul server, uno di solito crea un canale pieno il modo divertente (soprattutto se si vuole risolvere il problema TypeLevelFilter ala https://stackoverflow.com/a/9268223/344638):

BinaryServerFormatterSinkProvider serverProvider; 
BinaryClientFormatterSinkProvider clientProvider; 
Hashtable properties = new Hashtable(); 

serverProvider = new BinaryServerFormatterSinkProvider(); 
serverProvider.TypeFilterLevel = TypeFilterLevel.Full; 

clientProvider = new BinaryClientFormatterSinkProvider(); 

properties.Add("port", 8080); 

this.chan = new TcpChannel(properties, clientProvider, serverProvider); 

ChannelServices.RegisterChannel(this.chan, true); 

Diciamo che si sta utilizzando uno sponsor sul lato client. Se non lo fai, e il client non chiama l'oggetto comandate a distanza per un po ', il server rilasciare l'oggetto:

Object '/70c96e17_02a8_4e1a_a040_7b671b4a66b4/3fssua+asfozgeqqkrjql+4k_1.rem' has been disconnected or does not exist at the server. 

Così si sta utilizzando uno sponsor, che il server quindi chiama di tanto in tanto a rinnovare l'oggetto remoto. Ma! Ora il server ha un oggetto remoto: lo sponsor viene remotato sul lato server quando lo sponsor chiama ILease.Register. Ma se il server non ha un canale remoto verso il client, questo fallisce.

Quindi, nello stesso modo in cui il server deve esporre un canale remoto al client affinché il client possa accedere agli oggetti remoti, il client deve esporre un canale remoto al server affinché il server possa accedere remoto oggetti come sponsor. Alla fine, sia il mio lato client che quello server finiscono per avere lo stesso codice di costruzione del canale (sopra), tranne che io uso numeri di porta diversi su ciascun lato.

0

Per coloro che eseguono la ricerca nell'errore "Questo proxy remoto non ha sink di canale ...", ho ricevuto questo errore quando ho chiamato una libreria VB.NET con wrapping COM da VBScript. Tutto questo era sulla stessa macchina Windows 7 quindi non ci dovrebbero essere stati problemi con il client server. Alla fine ho scoperto che l'errore è stato causato da un carico di arraylists pieni di stringhe piuttosto che pieni di singoli che è quello che la funzione che stavo chiamando si aspettava. Non capisco perché ho ricevuto questo errore, ma spero che possa aiutare qualcuno a ottenere questo errore.