2009-09-25 8 views
5

J'ai donc une application qui a une API .NET disponible. Leur bibliothèque API communique avec leur application principale via des appels à distance .NET. Pour utiliser l'API, l'application doit déjà être opérationnelle. Par conséquent, j'ai une instance où j'ai besoin de démarrer par programme l'application, puis d'instancier l'un des objets API, qui tente d'ouvrir un canal d'accès distant IPC vers l'application principale. Le problème est qu'après le démarrage du processus, il y a quelques secondes entre le démarrage et le moment où l'application enregistre le canal. Si j'essaie d'instancier un objet API avant que le canal ne soit enregistré, il se déconnecte.Comment puis-je savoir si une autre application a enregistré un canal IPC Remoting?

Cela ne m'aide pas que je connaisse très peu de choses sur le remoting .NET.

Comment puis-je déterminer à partir de mon application qui utilise leur API si l'application THEIR a enregistré le canal pour la communication, donc je sais que c'est correct d'instancier leur objet API?

+0

Jon Skeet! Vous devez connaître la réponse! = [ – snicker

Répondre

2

Essayez ceci:

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

passe dans le port et vous devriez obtenir une valeur indiquant s'il y a un auditeur sur ce port.Hope cela aide

+1

Le problème est .. ce n'est pas un port. C'est IPC à distance, donc il y a des ports "noms" mais pas de ports réels. – snicker

+0

Si vous créez par programme un processus qui écoute les connexions, il doit écouter sur un port. Cet exemple MSDN a le serveur à l'écoute des appels IPC sur le port 9090: http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.ipc.ipcchannel.aspx Si vous n '' t connaissez le port, essayez d'exécuter netstat à partir de la ligne commannd, vous devriez être en mesure de voir quels ports sont utilisés –

+0

Ah, cela semble logique. Le port change au hasard, cependant. Des suggestions pour cela? – snicker

0

juste pour sortir de la boîte pour une avez-vous pensé à utiliser WCF avec MSMQ? Je ne suis pas sûr de bien comprendre que vous êtes une architecture, mais il semble que le client de l'API doit créer un autre processus qui héberge l'API. Il peut y avoir un problème de synchronisation entre lorsque vous démarrez l'hôte API et lorsque le client essaie d'effectuer des appels. Microsoft a récemment abandonné .NET Remoting (ainsi que toutes leurs autres technologies de communication précédentes, telles que les services Web ASMX) en tant qu'héritage, et recommande fortement que les développeurs passent à la plate-forme WCF.

Si vous utilisez WCF avec MSMQ, vous ne devriez pas avoir un problème de synchronisation. Votre application cliente peut déposer des messages dans une file d'attente durable, que l'hôte de l'API soit en cours d'exécution ou non. L'hôte API peut être démarré à tout moment, et il récupère et traite tous les messages en attente dans la file d'attente. Même si l'application cliente démarre toujours l'hôte API, le problème de temporisation ne sera plus un problème car vous utilisez la mise en file d'attente pour transférer les messages au lieu de .NET Remoting. WCF fournit un wrapper agréable, pratique et facile à utiliser autour de MSMQ, donc la barrière à l'entrée est relativement faible. L'autre avantage de l'utilisation de WCF sur .NET Remoting est que vous pouvez facilement déplacer l'hôte API vers un serveur physique différent sans avoir à changer l'application client. Vous pouvez même passer à une autre plate-forme de mise en file d'attente si vous le souhaitez (par exemple RabbitMQ sur AMQP), sans modifier les applications hôte client ou API. WCF gère toutes ces interactions pour vous, offrant un découplage beaucoup plus propre et des communications plus fiables entre votre application client et votre hôte API.

Si le déplacement vers WCF n'est pas une option, vous devriez pouvoir définir explicitement le port avec .NET Remoting. Je ne sais pas comment vous configurez votre hôte API, mais l'URL pour tout objet télécommandables donné est habituellement sous la forme de:

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

Si vous ajoutez le port, alors vous devriez être en mesure d'utiliser la solution de Abhijeet à déterminez si le port est ouvert ou non. Vous ne gagnerez pas le couplage lâche et les avantages de communications fiables de WCF, mais ce serait certainement moins de travail. ;)

+0

WCF n'est pas une option. Je ne contrôle pas la source du serveur. Il existe une application source fermée écrite dans un langage non géré (probablement C++) et une API fournie en tant que bibliothèque .NET. La bibliothèque est ce qui crée les objets à distance. Je dois utiliser l'accès à distance même si je sais qu'il est obsolète et suce. – snicker

0

Avez-vous envisagé d'encapsuler la tentative d'instancier l'objet API dans un bloc try-catch? Ensuite, vous pouvez analyser l'exception et voir si elle est due au fait que le serveur n'a pas écouté. Et si c'était le cas, vous pouvez simplement attendre et réessayer.

Est-ce logique?

+0

Oui, mais malheureusement, l'API de code source fermé est mal écrite, et définit certaines variables statiques qui l'empêchent d'être instancié à nouveau dans le même temps d'exécution sans utiliser des tonnes de réflexion pour le réparer. Ce serait une mauvaise solution. – snicker

+0

Faites-le dans un autre AppDomain alors? –

+0

J'ai essayé d'encapsuler myObj = Activator.GetObject (...) dans un bloc try-catch, en testant null, etc. Cela ne fonctionne pas car il renvoie un objet _TransparentProxy, que le serveur soit actif ou non. Ce n'est que plus tard lorsque vous essayez d'utiliser myObj que vous inclinez. Abjiheet a la bonne réponse, à mon avis. – IAbstract

0

Juste une petite faute de frappe dans le code. correction est la suivante:

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

Lorsque vous enregistrez un IpcServerChannel il fait un canal nommé à communiquer sur le nom du nom du port que vous avez choisi pour votre IpcServerChannel. Vous pouvez regarder la liste des tuyaux nommés pour voir si votre nom de port est là.

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