2009-11-17 11 views
2

J'ai un programme qui tire une liste d'adresses IP à partir d'une base de données, environ 3000 au total. Chaque adresse se rapporte à une machine distante qui doit exécuter un serveur .NET Remoting auquel mon application est le client. Je dois me connecter à chacun pour retirer certaines données via .Net Remoting. Cependant, s'il y a une sorte de problème sur le site distant, il y a une longue attente jusqu'à ce que le programme revienne.Vérification de port ouvert sur plusieurs machines

J'ai fait des recherches et trouvé que je peux vérifier le port .Net Remoting avant d'essayer une connexion .Net Remoting en utilisant des sockets. En outre, avec la méthode asynchrone Socket.BeginConnect, je peux temporiser toutes les connexions qui ne reviennent pas dans un délai d'attente spécifié. Cela fonctionne très bien lorsque je vérifie une adresse IP à la fois, mais pour X nombre d'adresses, cela peut potentiellement prendre (X * timeout) de temps pour terminer. Donc, ma prochaine étape était d'introduire un pool de threads afin que je puisse vérifier plusieurs sites en même temps:

Je crée un objet OpenPortChecker pour chaque ip dans une boucle, je l'envoie avec un ManualResetEvent et l'ip, puis je le place dans le pool de threads. Une fois que tous ont été ajoutés au pool, j'attends que tous les threads se terminent en parcourant la liste de ManualResetEvents et en appelant WaitOne() sur chacun d'eux. OpenPortChecker contient une méthode qui effectue un appel Socket.BeginConnect temporisé à l'adresse IP spécifiée comme détaillé ci-dessus, puis appelle ManualResetEvent.Set() pour signaler quand il a terminé. Mais cela ne fonctionne pas comme je l'avais prévu: si je ne limite pas la taille du pool de threads, toutes les connexions échouent en raison du timeout (même si je sais qu'elles sont disponibles) et finalement le programme échoue car trop de threads créé. En fait, je peux regarder le nombre de threads dans le Gestionnaire des tâches aller en haut et en haut, même si chaque thread devrait seulement vivre pendant le délai d'attente spécifié avant d'être retourné à la piscine. Cela peut être résolu en limitant la taille du pool de threads, mais la question du temps revient en jeu. De plus, à moins que je ne restreigne le pool (à environ 10 threads) et que je règle le délai à 20 secondes, aucune des connexions n'est réussie. Cela devient alors un jeu d'équilibrage entre le nombre de threads et le délai d'attente qui semble incorrect et peut fluctuer en fonction de la machine sur laquelle il est exécuté. En fait, il est discutable si c'est mieux que de vérifier une adresse à la fois. Est-ce que le nombre de connexions que je peux faire en même temps est limité?

Est-ce que je fais quelque chose de mal quelque part? Est-ce qu'il y a une meilleure approche? Toute aide serait appréciée.

Merci,

James

+1

Quel système d'exploitation utilisez-vous? Oui, il y a un nombre fini de connexions que vous pouvez faire - en particulier dans les systèmes d'exploitation non-serveur. –

+0

Salut. Je cours Windows XP Professionnel. Donc je dois limiter le nombre de threads pour correspondre au nombre de connexions autorisées? Le problème avec cette approche est qu'un utilisateur peut avoir d'autres applications en cours d'exécution qui utiliseront déjà une partie de ce quota. – James

+0

Pouvez-vous partager le code pour OpenPortChecker? –

Répondre

0

Pour autant que je sache, l'erreur est différente lorsque le site distant ne répond pas, lorsque le site distant connexion refuse et lorsque la connexion n'a pu être établie en raison d'une sorte du quota de connexion sortant. Gardez à l'esprit que la congestion de l'interface réseau simple pourrait être le coupable et pas n'importe quel type de quota.

0

Est-ce que les E/S non bloquantes sont disponibles en C#? Ensuite, en utilisant un thread, vous pouvez lancer plusieurs tentatives de connexion, et obtenir des rappels quand ils réussissent ou expirent.

1

Il semble que vous ayez la limitation tcpip.sys "half-open connections". si vous avez un de ces systèmes d'exploitation, vous avez cette limitation:

  • Windows XP Service Pack 2/3
  • Windows 2003 Service Pack 1 et plus
  • Windows Vista/2008 sans Service Pack ou Service Pack 1.
  • Windows 7 plus tôt que RTM.

Pour contourner cette limitation:

  • Sous Windows XP/2003 - installer le patch 3ème partie - http://www.lvllord.de
  • Sous Windows Vista/2008 - l'installation du Service Pack 2
  • Sous Windows 7 - Installer la version RTM.
0

Merci pour vos réponses. J'ai maintenant résolu ce problème, alors j'ai pensé que je posterais pour partager ma réponse si quelqu'un d'autre faisait face à un problème similaire. Comme Kieran Benton l'a souligné, il y a une limite au nombre de connexions permises par XP de 10 (cmd: net config server) donc j'ai limité mon programme pour exécuter seulement dix threads à la fois (bien qu'il reste un problème où un l'utilisateur peut déjà utiliser une partie du quota de connexion). Ensuite, travailler avec les informations fournies par Robert Obryk, je l'ai fait quelques recherches sur les connexions Remoting et découvert que vous pouvez en effet définir un délai lors de la connexion à distance via:

IDictionary prop = ChannelServices.GetChannelSinkProperties(remObject); 
prop["timeout"] = remotingTimeout; 

À ce stade, je suis passé la première Connexion Socket temporisée car il semblait que ce n'était plus nécessaire, mais les tests ont montré que le délai d'attente Remoting n'était efficace que si la machine distante était accessible via le port spécifié. Si le port était fermé, le délai d'expiration a été ignoré et la connexion a été suspendue. Donc, ma mise en œuvre finale implique une connexion Socket temporisée pour d'abord vérifier que le port est ouvert, puis tenter un appel Remoting temporisé aux sites sensibles. Un peu long mais ca marche!

Merci encore,

James

Questions connexes