12
votes

Un processus inter-plate-forme simple pour traiter la communication dans Mono?

Je travaille sur une application mono qui fonctionnera sur Linux, Mac et Windows, et besoin de la possibilité pour les applications (sur un seul système d'exploitation) d'envoyer des messages de chaîne simples les uns aux autres.

Spécifiquement, je veux une seule application d'instance. Si une deuxième instance est tentée à être démarrée, elle envoie un message à la seule instance déjà en cours d'exécution.

DBU est sorti, car je ne veux pas avoir que ce soit une exigence supplémentaire. La communication de la prise semble être difficile, car les fenêtres semblent ne pas autoriser la permission de se connecter. Les fichiers mappés de mémoire semblent ne pas être pris en charge dans Mono. Les tuyaux nommés ne semblent pas être pris en charge dans Mono. IPC semble ne pas être pris en charge sur mono.

Alors, existe-t-il une méthode simple pour envoyer des messages de chaîne sur une seule machine à une application de serveur qui fonctionne sur chaque système d'exploitation, sans exiger des autorisations ni des dépendances supplémentaires?


2 commentaires

Je vois que vous vous êtes déjà installé sur quelque chose, mais quel était exactement le problème des sockets? Windows ne permettrait pas à un auditeur d'être démarré ou que vous ne pouviez pas vous connecter à la prise ouverte? Notez que vous pouvez créer des sockets qui ne sont ouverts qu'à la localhost et non externes à la machine. Les fenêtres peuvent nécessiter moins de droits pour le faire.


Un problème, un problème. Le problème: J'aurais besoin de savoir quelle prise à utiliser, par utilisateur. Je pourrais utiliser un hachage à distance, mais pourrait vous retrouver avec une collision. Les namedPipes n'ont pas encore été implémentées dans Mono 2.6, autant que je sache. Le problème: J'ai eu une erreur sous Windows que la connexion a été rejetée car l'hôte n'a pas accepté la demande de connexion (ou quelque chose à cet effet ... impossible de trouver un message d'erreur exact). Ma solution évite ces deux questions et fonctionne bien jusqu'à présent.


4 Réponses :


5
votes

sur mon ubuntu (version 10.10 mono: 2.6.7) J'ai essayé d'utiliser WCF pour la communication interprocessive avec BasichttpLinding, Nettcpbinding et NetNamedpipeDinging. Les 2 premiers ont fonctionné bien, pour NetNamedpipeLinding, j'ai eu une erreur:

iDuppexSession de type canalChannel est non supporté

Lorsque vous appelez la méthode canaysory.Createcherannel ().

J'ai aussi essayé d'utiliser Remoting (qui est une technologie héritée depuis la sortie de la WCF) avec IPCChannel; Exemple de ce Page MSDN a commencé et travaillé sans problèmes sur ma machine.

Je suppose que vous ne devriez pas avoir de problèmes à l'aide de WCF ou de télécommander sur des fenêtres non plus, pas sûr de Mac cependant, n'en avez pas d'entre eux pour tester. Faites-moi savoir si vous avez besoin d'exemples de code.

J'espère que cela aide, considère


4 commentaires

+1 pour la liaison HTTP de base WCF et ainsi de suite. La liaison HTTP de base a été la première pièce de la mise en œuvre de la WCF en mono, elle devrait donc fonctionner correctement dans la plupart des scénarios (même sur Mac OS X). Mais d'autres liaisons sont encore en cours de développement IMHO, de sorte que les insectes doivent être isolés et rapportés à Mono chaque fois que possible. La télécommande est obsolète par WCF, il n'est donc pas recommandé de l'utiliser plus dans de nouveaux projets.


Malheureusement, BasichttpLinding crée des problèmes sur Windows avec .NET. Il faut que l'utilisateur exécute la commande netsh sur la console d'administrateur ( social.msdn.microsoft.com/forums/vstudio/en-us/... ), qui peut ne pas toujours être Disponible pour les utilisateurs de l'environnement d'entreprise.


Netcpbinding a fonctionné à la fois sur mono sur Linux et .NET sous Windows. Merci.


@SergiybyElozyorov, http peut fonctionner pour les utilisateurs de privilèges faibles, il vous suffit de spécifier le correcteur hostcomeComeNode . Voir Stackoverflow.com/a/27882705/138200



1
votes

Pour votre simple raison pour avoir besoin d'IPC, je chercherais une autre solution.

Ce code est confirmé pour fonctionner sur Linux et Windows. Devrait fonctionner aussi sur Mac: xxx

juste itérer dans la liste et recherchez votre propre nom de processus.

Pour envoyer un message à votre application, juste Utilisez myProcess.standardnput pour écrire sur l'entrée standard des applications. Cela ne fonctionne que si votre application est une application d'interface graphique.

Si vous avez des problèmes avec cela, vous pouvez peut-être utiliser un fichier "verrou" spécialisé. En utilisant la classe FilesSystemWatcher, vous pouvez vérifier quand il change. De cette façon, la deuxième instance pourrait écrire un message dans le fichier, puis l'avis de première instance qu'il modifie et peut lire dans le contenu du fichier pour obtenir un message.


4 commentaires

Je pense que c'est la méthode la plus simple et la plus robuste. Je devrai être pour commencer mon instance unique avec RedirectinUcipant activé, mais je pense que c'est la meilleure option globale. Merci!


Sauf qu'il semble que je ne puisse pas vous reconnecter sur la normalisation du processus de course. Qui défait ensuite le but. Cela signifie que je ne peux pas utiliser la redirection, à l'exception du processus d'origine qui a commencé l'instance unique. Ai-je raison? Si oui, je cherche toujours une solution ...


@ D.S. Je ne suis pas sûr d'être honnête, je viens de connecter quelques classes. Je n'ai pas essayé cette méthode moi-même.


@ D.S. Pour répondre à vos problèmes avec l'entrée standard du processus, examinez ma suggestion supplémentaire d'utiliser la classe FilesSystemwatcher pour implémenter votre propre IPC simpliste



1
votes

a résolu mon problème avec deux techniques: un mutex nommé (de sorte que l'application puisse être exécutée sur la même machine par différents utilisateurs) et un observateur sur un fichier de message. Le fichier est ouvert et écrit pour la communication. Voici une solution de base, écrite dans IronPython 2.6:

(mutex, locked) = System.Threading.Mutex(True, "MyApp/%s" % System.Environment.UserName, None)
if locked:
    watcher = System.IO.FileSystemWatcher()
    watcher.Path = path_to_user_dir
    watcher.Filter = "messages"
    watcher.NotifyFilter = System.IO.NotifyFilters.LastWrite
    watcher.Changed += handleMessages
    watcher.EnableRaisingEvents = True
else:
    messages = os.path.join(path_to_user_dir, "messages")
    fp = file(messages, "a")
    fp.write(command)
    fp.close()
    sys.exit(0)


3 commentaires

Malheureusement, cela ne devrait pas être considéré comme une réponse, pour deux raisons: System.Threading.Mutex peut être utilisé pour la synchronisation sous Windows Inter-Process, et je ne connais pas le Linux, mais sur Mac OSX, il ne peut être utilisé que pour Synchronisation inter-thread. Ne fonctionne pas pour inter-processus. De même, FilesSystemwatcher fonctionne parfaitement sur Windows et Linux, mais pas sur Mac OSX, Solaris ou d'autres systèmes UNIX basés sur KQueue.


Vous avez raison. J'ai trouvé que cela ne fonctionnait pas sur toutes les plateformes. Toujours à la recherche d'une solution.


Vous pouvez le marquer comme une réponse, ne pouvez-vous pas? C'était la page que j'ai trouvée quand je cherchais une réponse similaire, de sorte que la réponse "répondue" me m'a conduit un instant jusqu'à ce que je l'ai découverte ne fonctionnait pas. J'ai continué à travailler après cela, et je vais écrire une nouvelle réponse momentanément ...



3
votes

J'ai écrit à ce sujet sur la liste de diffusion mono-dev. Plusieurs systèmes de messagerie inter-traitants à usage général ont été pris en compte, y compris des DBU, System.Threading.Threading.Mutex Class, WCF, Remoting, Named Tipes ... Les conclusions étaient fondamentalement mono ne prend pas en charge la classe Mutex (fonctionne pour inter-thread , pas pour inter-processus) et Il n'y a rien de plate-forme agnostique disponible .

Je n'ai pu imaginer que trois solutions possibles. Tous ont leurs inconvénients. Peut-être qu'il y a une meilleure solution disponible, ou peut-être de meilleures solutions à des fins spécifiques ou peut-être il existe des bibliothèques de 3ème plate-forme croisées que vous pourriez inclure dans votre application (je ne sais pas.) Mais ces sont les meilleures solutions que j'ai pu trouver jusqu'à présent:

  • Ouvrez ou créez un fichier dans un emplacement connu, avec une serrure exclusive. (Fileshare.none). Chaque application essaie d'ouvrir le fichier, de faire son travail et de fermer le fichier. Si vous ne pouvez pas ouvrir, filez-vous (1) et réessayez. C'est une sorte de ghetto, mais cela fonctionne la plate-forme inter-plate-forme pour fournir un mutex inter-processus.
  • Sockets. La première application écoute sur localhost, un port numéroté élevé. Deuxième application tentative d'écoute sur ce port, ne parvient pas à ouvrir (car un autre processus le contient déjà), un second processus envoie un message au premier processus, qui est déjà écouté sur ce port.
  • Si vous avez accès à une base de données transactionnelle ou à un système de passage de message (SQS, rabbbitmq, etc.), utilisez-le.
  • Bien sûr, vous pouvez détecter quelle plate-forme vous utilisez, puis utilisez tout ce qui fonctionne sur cette plate-forme.

0 commentaires