Solution pour la découverte de pairs LAN légers?


9

J'ai construit une bibliothèque pour une programmation purement multiplateforme. Mes jeux créés avec lui fonctionnent bien sous Android, Pc, Linux, Mac, etc.

Les capacités de mise en réseau sont fournies par la bibliothèque ENET, donc toutes les communications entre mes applications ne sont pas compatibles TCP ou UDP, mais uniquement dans le protocole personnalisé, même difficile, basé sur l'UDP en fin de compte.

Je ne pense pas qu'il soit possible de faire ce que je veux avec ENET, c'est pourquoi je demande ici de l'aide!

Disons que j'ai le même jeu en cours d'exécution sur mon téléphone Android, mon ordinateur portable et mon PC. Ils sont tous dans le même réseau wifi, et donc dans un LAN, que ce soit son hotspot Wifi (?) Ou le routeur domestique.

J'ai besoin que chacun de ces 3 pairs découvre les deux autres du réseau. Ceci est uniquement destiné à trouver l'IP des applications actives dans le réseau LAN, pour pouvoir héberger des jeux multijoueurs entre elles.

Je ne peux penser qu'à un moyen efficace de le faire, la diffusion UDP, attendre les réponses, mais si c'est la solution, j'ai besoin de quelque chose de petit, car c'est le seul but de la mise en œuvre.

Une autre façon pourrait être d'essayer de se connecter à toutes les adresses IP dans la sous-plage d'adresses LAN, mais je ne pense pas que le système d'exploitation serait avec moi sur celui-ci: p


2
Je pense que quelques émissions UDP sont la voie à suivre, et je ne comprends pas vos objections, ou est-ce qu'ENET ne prend pas en charge les émissions?
Roy T.

Exactement, ce n'est pas le cas, il ne peut être diffusé qu'à des pairs déjà connus.
Grimshaw

stackoverflow.com/questions/683624/… Est-ce que cela influence une réponse?
Grimshaw

Réponses:


5

Comme beaucoup de gens l'ont dit, la solution serait d'utiliser la diffusion UDP , mais il y a beaucoup de détails de mise en œuvre impliqués. J'ai récemment rencontré le même problème et après avoir élaboré une solution, j'ai créé un blog et un exemple de projet sous la forme d'un serveur / client de chat LAN. Je vais les résumer ici, mais vous devriez les vérifier pour plus de détails et du vrai code.

Voici comment cela fonctionne, basé sur une description de Lee Salzman, créateur d'ENet:

  • Votre serveur de jeu fonctionne sur un socket, en tant qu'hôte ENet
  • Le serveur se lie également à un port "d'écoute" connu, en tant que socket UDP standard (c'est-à-dire pas un hôte ENet)
  • Le client envoie un message de diffusion UDP (c'est-à-dire IP 255.255.255.255) à ce port d'écoute et attend les réponses
  • Tous les serveurs du LAN recevront ce message de «numérisation» et répondront. Idéalement, vous pouvez répondre avec le port sur lequel le serveur de jeu (hôte ENet) s'exécute; de cette façon, vous n'avez pas besoin que votre serveur de jeu fonctionne sur un port fixe)
  • Une fois que le client a reçu des réponses, il saura quels serveurs sont présents. Ensuite, vous pouvez choisir l'un d'eux pour vous connecter, en tant que pair ENet normal. À ce stade, le client n'a plus besoin de la prise "scanner" UDP.

La bonne nouvelle est que ENet fournit des fonctions d'encapsulation pour l'utilisation des sockets , vous pouvez donc tout faire dans ENet. La mauvaise nouvelle est que l'emballage est extrêmement mince; vous aurez besoin de connaître la programmation des sockets , comme quoi select()faire. C'est pourquoi je vous encourage à jeter un œil à l' article de blog et à l' exemple de projet afin de pouvoir copier / coller le code et vous faire gagner beaucoup de temps.

Voici quelques notes et pièges si vous choisissez de faire votre propre implémentation:

  • L'écouteur / scanner doit être UDP, vous devez donc les créer en utilisant enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(ou SOCK_DGRAMpour une programmation de socket ancienne)
  • Pour l'écouteur du serveur, autorisez la réutilisation de l'adresse du port à l'aide de enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(ou SO_REUSEADDR) afin que plusieurs serveurs puissent s'exécuter sur la même IP.
  • Pour le "scanner" client, vous devez activer les diffusions sur le socket UDP en utilisant enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(ou SO_BROADCAST), sinon vous ne pourrez pas envoyer à l'adresse de diffusion. Il s'agit uniquement d' une fonction de sécurité qui rend plus difficile l'inondation accidentelle du réseau.

Malheureusement, ce n'est pas exactement une solution "légère"; l'exemple de projet se situe à quelques centaines de LOC au total. Ce serait bien si cela était empaqueté dans une bibliothèque d'utilitaires pour ENet, mais j'ai trouvé que pour les serveurs de jeux, vous souhaitiez souvent envoyer des informations plus spécifiques au jeu avec la réponse du serveur pour rendre cela utile, comme:

  • Le type de jeu (par exemple "coop", "match à mort")
  • La «carte», le «niveau» ou la «campagne» que le serveur exécute
  • Le nombre de joueurs et de joueurs max pour le serveur
  • Toute autre information spécifique au jeu qui affectera la décision du client de se connecter ou non. Pensez aux «navigateurs de serveur» dans les jeux et au type d'informations qu'ils affichent.

C'est exactement ce que je pensais. La radiodiffusion est la voie à suivre.
Lolums

3

Lorsque vous ne voulez pas quitter votre bibliothèque, vous pouvez simplement utiliser la force brute et tenter de vous connecter à chacune des adresses possibles. La plupart des réseaux locaux résidentiels sont des réseaux de classe C (/ 24) où les 24 premiers bits de l'adresse IP sont identiques et les 8 derniers bits diffèrent. Vous n'avez donc que 255 adresses IP possibles.

Mais quand même, faire une diffusion UDP serait l'alternative la plus propre. Envoyez simplement un paquet UDP au 255.255.255.255 et tous les clients derrière le même routeur le recevront. Ils peuvent ensuite envoyer une réponse à l'adresse IP source et au port source du paquet pour informer l'expéditeur de leur présence.


2
S'il vous plaît s'il vous plaît s'il vous plaît s'il vous plaît s'il vous plaît ne forcez pas brutalement.
Trevor Powell

@TrevorPowell ... parce que ...?
Philipp

2
Parce que ce n'est pas la bonne solution. Cela ne fonctionnera pas dans les universités (qui n'utilisent pas de réseaux de classe c) ou dans les entreprises (qui généralement n'utilisent pas non plus de réseaux de classe c), et le personnel informatique de l'une ou l'autre détestera intensément la charge causée par le fait que chaque joueur fasse brute-force tente d'envoyer des messages à chaque adresse IP de son réseau chaque fois qu'ils cliquent sur un bouton «Actualiser». C'est juste une mauvaise solution au problème . Cette question de localiser des pairs potentiels sans serveur de mathématiques est précisément à quoi sert la diffusion. Utilisez la diffusion. C'est mieux dans tous les sens. :)
Trevor Powell

1

Vous pouvez jeter un œil à DNS-SD / ZeroConf / Avahi / Bonjour / mDNS . C'est ce que Apple utilise pour partager des imprimantes, des dossiers iTunes, etc., mais il a été adopté ailleurs. Avahi est la version open source que Linux utilise (je ne sais pas si c'est uniquement Linux), je ne sais pas à quel point tout est portable (bien qu'il existe des implémentations pour la plupart des plates-formes).

Cela dit, il est probablement plus facile de simplement faire la diffusion UDP.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.