2009-09-25 13 views
5

Quindi ho un'applicazione con API .NET disponibile. La loro libreria API comunica con la loro applicazione principale tramite le chiamate remote .NET. Per utilizzare l'API, l'applicazione deve essere già attiva e funzionante.Come posso sapere se un'altra app ha registrato un canale Remoto IPC?

Quindi, ho un'istanza in cui è necessario avviare l'applicazione a livello di codice e quindi creare un'istanza di uno degli oggetti API, che tenta di aprire un canale remoto IPC nell'app principale. Il problema è che, dopo aver avviato il processo, ci sono alcuni secondi tra l'avvio e quando l'applicazione registra il canale. Se provo a creare un'istanza di un oggetto API prima che il canale sia registrato, si biffica.

Non aiuta che io sappia molto poco su .NET remoting.

Come determinare dall'applicazione MY che utilizza la loro API se l'applicazione THEIR ha registrato il canale per la comunicazione quindi so che è opportuno creare un'istanza del proprio oggetto API?

+0

Jon Skeet! Devi conoscere la risposta! = [ – snicker

risposta

2

Prova questo:

using System.Net.NetworkInformation; 
using System.Net; 
private static bool IsPortAvailable(int port) 
{ 
     IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); 
     IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); 
     if (activeListeners.Any(conn => conn.Port == port)) 
     { 
      return true; 
     } 
     return false; 
} 

Passo nel porto e si dovrebbe ottenere un valore che indica se c'è un ascoltatore su quel port.Hope questo aiuta

+1

Il problema è .. non è una porta. È il servizio remoto IPC, quindi ci sono "nomi" di porta ma non porte effettive. – snicker

+0

Se si sta creando in modo programmatico un processo che ascolta le connessioni, deve essere in ascolto su alcune porte. Questo esempio MSDN ha il server che ascolta le chiamate IPC sulla porta 9090: http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.ipc.ipcchannel.aspx Se non si Conosco la porta, prova a eseguire netstat dalla riga di comando, dovresti essere in grado di vedere quali porte sono in uso –

+0

Ah, che sembra avere senso. La porta cambia casualmente, comunque. Qualche suggerimento per quello? – snicker

0

solo per uscire dalla scatola per un momento, hai pensato di usare WCF con MSMQ? Non sono sicuro di comprendere appieno la tua architettura, ma sembra che il client dell'API debba avviare un altro processo che ospita l'API. Potrebbe esserci un problema di temporizzazione tra quando si avvia l'host dell'API e quando il client tenta di effettuare chiamate. Recentemente Microsoft ha deprecato .NET Remoting (e tutte le altre tecnologie di comunicazione precedenti come i servizi Web ASMX) come legacy e raccomanda vivamente agli sviluppatori di passare alla piattaforma WCF.

Se si utilizza WCF con MSMQ, non si dovrebbe avere un problema con i tempi. L'applicazione client può rilasciare i messaggi in una coda duratura indipendentemente dal fatto che l'host API sia in esecuzione o meno. L'host API può essere avviato in qualsiasi momento e raccoglierà ed elaborerà tutti i messaggi in attesa in coda. Anche se l'applicazione client avvia l'host API, il problema di temporizzazione non sarebbe più un problema, in quanto si utilizza la messa in coda per trasferire i messaggi anziché .NET Remoting. WCF fornisce un involucro bello, conveniente e facile da usare intorno a MSMQ, quindi la barriera all'ingresso è relativamente bassa.

L'altra cosa bella dell'utilizzo di WCF su .NET Remoting è che è possibile spostare facilmente l'host API su un server fisico diverso senza dover modificare le app client. Potresti persino passare a una diversa piattaforma di accodamento se lo desideri (come RabbitMQ su AMQP), senza modificare le app host client o API. WCF gestisce tutta questa interazione per te, fornendo un disaccoppiamento molto più pulito e comunicazioni più affidabili tra l'app client e l'host API.

Se lo spostamento verso WCF non è un'opzione, dovresti essere in grado di impostare esplicitamente la porta con .NET Remoting. Io non sono sicuro di come si sta configurando il vostro ospite API, ma l'URL di un dato oggetto telecomandato è di solito sotto forma di:

tcp://<hostname>[:<port>]/<object> 

Se si aggiunge la porta, allora si dovrebbe essere in grado di utilizzare la soluzione di Abhijeet a determinare se la porta è aperta o meno. Non otterrete l'accoppiamento libero e i vantaggi di comunicazione affidabili di WCF, ma sarebbe sicuramente meno lavoro. ;)

+0

WCF non è un'opzione. Non controllo la fonte del server. Esiste un'applicazione di origine chiusa scritta in un linguaggio non gestito (probabilmente C++) e un'API fornita come libreria .NET. La libreria è ciò che crea gli oggetti remoti. Devo usare il servizio di remoting anche se so che è deprecato e fa schifo. – snicker

0

Hai considerato di completare il tentativo di istanziare l'oggetto API in un blocco try-catch? Quindi puoi analizzare l'eccezione e vedere se è stata causata dal mancato ascolto del server. E se lo fosse, puoi solo aspettare e riprovare.

Ha senso?

+0

Sì, ma sfortunatamente l'API closed source è scritta male e imposta alcune variabili statiche che impediscono di essere istanziato di nuovo nello stesso runtime senza utilizzare tonnellate di riflessione per risolverlo. Sarebbe una brutta soluzione. – snicker

+0

Fallo allora in un altro AppDomain? –

+0

Ho provato a racchiudere myObj = Activator.GetObject (...) in un blocco try-catch, test per null, ecc. Non funziona perché restituisce un oggetto _TransparentProxy indipendentemente dal fatto che il server sia attivo o meno. Non è più tardi quando tenti di usare myObj che inclini. Abjiheet ha la risposta giusta, secondo me. – IAbstract

0

Solo un piccolo refuso nel codice. correzione è la seguente:

using System.Net.NetworkInformation; 
using System.Net; 
private static bool IsPortAvailable(int port) 
{ 
    IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); 
    IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); 
    if (activeListeners.Any(conn => conn.Port == port)) 
    { 
     return true; 
    } 
    return false; 
} 
0

Quando si registra un IpcServerChannel fa una named pipe per comunicare sopra con il nome del nome della porta si è scelto per la vostra IpcServerChannel. Puoi guardare l'elenco dei Named Pipe per vedere se il tuo Nome Port è lì.

System.IO.Directory.GetFiles(@"\\.\pipe\").Any((path) => path.Contains(@"\\.\pipe\" + pipeName)); 
Problemi correlati