-
trouver les hotes
Bonjour,
quelqu'un pourait-il m'indiquer le principe pour trouver (sur le reseau local) tous les serveurs correspondant à l'application?
exemple : comment un jeu trouve-t-il toutes les adresses des serveurs qui hebergent une partie ?
merci de vos indications :wink:
-
re
Tu as deux méthodes :
1° la méthode brute
La méthode brute consiste a passer toutes les adresses du réseau local pour voir si l'un deux répond sur le port du serveur. C'est une solution 'auto' mais qui peut générer beaucoup de traffic et prendre un temps bête.
2° la méthode "annuaire"
Tu as un serveur central qui sert d'annuaire. Dès qu'un serveur est lancé, il se connecte sur le central pour lui signaler qu'il est online. Le serveur, tant qu'il est connecté, peut signaler un refresh toutes les 10 minutes (par exemple) au central. Si le central voit qu'un serveur n'a pas fait son refresh, il le vire de l'annuaire. Lorsque ton client veut se connecter à un serveur, il interroge le central pour avoir la liste des serveurs disponibles.
Il me semble que sur Counter Strike, c'est le prinicpe du serveur central (le serveur WON je crois)
-
ok donc dans le cadre de la "methode brute", il suffit de tenter une connection socket (try-catch?) de toutes les adresses du reseau local auquel on appartient. L'operation me semble gourmande en ressource mais je tente le coup (apres tout counterstrike procede comme ca en LAN je croi)
merci :wink:
-
heu au fait... comment on fait pour obtenir l'adresse ip de la machine local (pas localhost ni 127.0.0.1) ainsi que le masque sous reseau ?
sans ca je voi pas comment faire ma boucle de parcour des adresses locales ...
:roll: :roll:
-
re
Sous Linux : ça se trouve dans un fichier /proc
Sous Windows : ça doit se trouver dans la base de registre au niveau de la configuration réseau mais alors où exactement..., il faut faire une recherche sur Google ou dans le forum.
Ou alors, tu fais un regedit et tu fais une recherche sur ton adresse de réseau LAN, et tu regardes quel est la clé qui correspont à cet info. Mais attention en jouant avec la base de registre, les paramètres peuvent être différents d'un windows à l'autre (c'est à vérifier)
-
ok j'ai trouver comment avoir l'ip (ClientSocket->Socket->RemoteAddress) :wink:
mais j'ai encore des soucis ....
voila comment je procede:
un boucle qui pour chaque adresse ip, ouvre la socket, la ferme et passe a la suivante.
le try catch sur socket->open() ne revoi pas d'erreur sur la connection , donc j'utilise l'envennement OnClientConnect pour savoir si une connection s'est ouverte.
mon probleme:
lorsque l'evennement OnClientConnect survient, la valeur de la propriete Adresse est toujours 254 (la valeur prise à la fin de ma boucle)
autrement dit, le programme effectue la boucle qui scanne les ip du reseau, puis les evennements sur l'objet clientsocket arrivent (donc de maniere asynchrone)
avec ce decalage je peux pas savoir quelle adresse a repondu ...
->j'ai lu quelque chose sur le handle dans la doc mais j'ai pas compris et je sais pas si c'est la solution à mon probleme
->une autre solution me vien a l'esprit; trouver un moyen de mettre en attente le programme juste apres le ClientSocket->Open() pour attendre que l'evennement OnClientConnect ou OnClientError survienne ... mais je n'ai aucune idee sur le procédé.
un peu d'aide serait la bienvenue :oops: :oops:
-
re
Il me semble que lorsqu'un socket est ouvert, tu peux obtenir l'adresse IP du serveur sur lequel il est connecté. L'event OnClientConnect te fournit un Socket en paramètre je crois. Sur ce socket-là, tu peux avoir l'adresse.
La valeur de la propriété Adresse dont tu parles (celle qui est à 254), tu la prends d'où ? Du ClientSocket ?
Evites de mettre des choses en attente, ce serait, à mon avis, une grosse perte de temps.
-
c'est bien ca mon probleme
Socket->RemoteAddress de l'evennement OnClientConnect me retourne l'ip 255 (soit celle de ma fin de boucle)
ce qui veux dire que ce n'est pas le socket qui a reussi a se connecté que j'utilise mais le dernier que j'ai ouvert ...
-
re
Bon, essaies cette solution :
A chaque fois que tu lances un ClientSocket pour ce connecter, tu notes dans un tableau à deux entrée l'handle du socket et le nr d'hote que tu testes.
De cette manière, lorsque tu reçois une connection (OnClientConnect), tu récupères le handle de socket et tu le compare à ta liste handle/nr hote.
Ou alors, je viens de me rappeler qqch, tu peux définir les ClientSocket en bloquant (!= du non-bloquant).
Ce sont deux voies qui me viennent à l'esprit...
-
j'ai essayer la methode de mise en attente (lance une requete sur une ip et attente de la reponse pour tester une autre ip) mais c'est beaucoup trop lent! (1min pour 7 ip ...)
j'ai essayer aussi avec un handle mais c'est le meme probleme qu'avec l'adresse du socket , c'est a dire que sur les evennement OnClientConnect ou OnClientError, je handle recu est celui de la derniere socket ouverte (ip .254)
je suis dans une impasse ... :cry: :cry:
-
re
Il y a toujours une solution ;-)
Je viens de penser à une chose, lorsque tu as un OnClientConnect, pq le serveur ne t'enverrais pas une ligne d'identification avec son adresse IP ?
Le serveur peut lire son adresse IP dans la base de registre et dès que le serveur reçoit une connection entrante sur le port, il balances un ID sur le socket que tu peux réceptionner au niveau de ton client pour le mettre dans une liste de serveur disponible.
Qu'en penses-tu ?
-
merci mais je ne veux pas recevoir de reponse de la part des serveurs ...
enfin j'ai trouvé !!
pour info voila la soluce :
Recherche des machines connectées au reseau local:
1. je recupere l'ip locale
2. avec une boucle, pour chaque ip du reseau (1 à 254) j'envoi un ping avec l'objet TIdIcmpClient
3. a chaque ip qui me repond OnIdIcmpClientReply, je la mémorise dans un tableau
Recherche des machines locales qui sont des serveurs:
1. j'active mon objet TcpClient sur la premiere adresse de mon tableau
2. lorque je recoi une reponse alors je passe à la suivante (OnTcpClientError et OnTcpClientConnect), je stock bien sur l'adresse si elle a répondu
et je boucle ansi pour toutes les adresses de mon tableau.
BILAN : 15-20sec de recherche pour scaner le reseau et trouver les serveurs, et 5-10 sec pour rafraichir (rechercher a partir du tableau de machines connectées)
BUG: pendant ces 20sec, le programme est comme planté (on ne peut rien faire tout est bloqué)
-
Bonjour,
Juste un commentaire. Tu suppose que le réseau est un réseau de classe C, c'est à dire que seuls les 8 derniers bits sont les identifiants d'hôte. Mais si quelqu'un décide de faire tourner ton appli sur un réseau de classe B ? ou pire, A (on peut rêver...)
Je dis peut-être une bétise, mais est-ce qu'un envoi de broadcast de la part du client ne serait pas plus approprié ? Les serveurs recevant ce broadcast le traiteraient et renveraient une réponse. Le client pourrait ainsi construire sa liste de serveurs au gré des réponses reçues...
De plus, la technique du broadcast a un certain avantage, vu qu'elle permet de se libérer des caractéristiques du réseau, et que cela réduit finalement le nombre de requêtes, et le temps nécessaire.
Cordialement,
Arnaud
-
j'y ai songé mais une ouverture TCP vers une adresse de broadcast me revoi toujours une erreur ... peut etre que je ne sais pas le faire ... :lol:
quand aux adresses autres que de classe C, c'est qu'une question de boucle , suffit de boucler sur les 3 derniers octets. (sachant que je met 20sec max pour scaner une classe C, je mettrai ... heuu.. c dur la ... 360h pour une classe A :roll: :roll: )
donc je prefere verifier seulement le dernier octet :lol: :lol:
-
J'ai bien suivi vos explication mais je n'arrive pas à utiliser la commande Ping().
Je n'arrive pas à utiliser OnIdIcmpClientReply que vous préconisez
L'évenement OnReply de IdIcmpClient me repond même si l'adresse pinger n'est pas présente.
Quelqu'un pourrait m'aider