Rozwiązanie dla lekkiego odkrywania peer LAN?

9

Zbudowałem bibliotekę do programowania wyłącznie między platformami. Moje stworzone z nim gry działają dobrze w systemach Android, PC, Linux, Mac itp.

Możliwości sieciowe są zapewniane przez bibliotekę ENET, dlatego cała komunikacja między moimi aplikacjami nie jest kompatybilna z TCP ani UDP, ale tylko w niestandardowym protokole, nawet w ostateczności opartym na UDP.

Nie sądzę, aby można było robić to, co chcę z ENET, dlatego tutaj proszę o pomoc!

Powiedzmy, że mam tę samą grę na telefonie z Androidem, laptopie i komputerze. Wszystkie są w tej samej sieci Wi-Fi, a zatem w sieci LAN, niezależnie od tego, czy jest to hotspot Wi-Fi (?), Czy router domowy.

Potrzebuję każdego z tych 3 peerów, aby odkryć pozostałe dwa w sieci. Ma to na celu jedynie znalezienie adresu IP żywych aplikacji w sieci LAN, aby móc hostować między nimi gry wieloosobowe.

Mogę wymyślić tylko jeden skuteczny sposób na to, transmisję UDP, czekanie odpowiedzi, ale jeśli to jest rozwiązanie, potrzebuję czegoś małego, ponieważ jest to jedyny cel wdrożenia.

Innym sposobem może być próba połączenia się ze wszystkimi adresami IP w podzakresie adresu LAN, ale nie sądzę, aby system operacyjny był ze mną na tym: p

Grimshaw
źródło
2
Myślę, że kilka transmisji UDP jest już na dobrej drodze i nie rozumiem twoich sprzeciwów wobec tego, czy może ENET nie obsługuje transmisji?
Roy T.
Dokładnie tak nie jest, może transmitować tylko do znanych już rówieśników ..
Grimshaw,
stackoverflow.com/questions/683624/... Czy to wpływa na odpowiedź?
Grimshaw,

Odpowiedzi:

5

Jak wiele osób mówiło, rozwiązaniem byłoby użycie transmisji UDP , ale wiąże się to z wieloma szczegółami dotyczącymi implementacji. Niedawno napotkałem ten sam problem i po opracowaniu rozwiązania napisałem post na blogu oraz przykładowy projekt w postaci serwera / klienta czatu LAN. Podsumuję je tutaj, ale powinieneś sprawdzić je, aby uzyskać więcej szczegółów i prawdziwy kod.

Oto, jak to działa, na podstawie opisu Lee Salzman, twórcy ENet:

  • Twój serwer gier działa na jednym gnieździe, jako host ENet
  • Serwer łączy się również ze znanym portem „nasłuchiwania” jako zwykłym gniazdem UDP (tzn. Nie hostem ENet)
  • Klient wysyła komunikat rozgłoszeniowy UDP (tj. IP 255.255.255.255) do tego portu nasłuchiwania i czeka na odpowiedzi
  • Wszystkie serwery w sieci LAN otrzymają ten komunikat „skanowania” i odpowiedzą. Idealnie możesz odpowiedzieć za pomocą portu, na którym działa serwer gry (host ENet); w ten sposób nie musisz mieć serwera gry działającego na stałym porcie)
  • Po otrzymaniu odpowiedzi klient będzie wiedział, które serwery są obecne. Następnie możesz wybrać jeden z nich, z którym chcesz się połączyć, jako zwykły partner ENet. W tym momencie klient nie potrzebuje już gniazda „skanera” UDP.

Dobrą wiadomością jest to, że ENet zapewnia funkcje otoki dla korzystania z gniazd , dzięki czemu możesz zrobić wszystko w ENet. Zła wiadomość jest taka, że ​​opakowanie jest wyjątkowo cienkie; musisz wiedzieć o programowaniu gniazd , na przykład o tym, co select()robi. Dlatego zachęcam do przejrzenia posta na blogu i przykładowego projektu , abyś mógł skopiować / wkleić kod i zaoszczędzić sobie dużo czasu.

Oto kilka uwag i pułapek, jeśli zdecydujesz się na własną implementację:

  • Słuchacz / skaner musi mieć format UDP, więc musisz je utworzyć za pomocą enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(lub SOCK_DGRAMdo zwykłego programowania starego gniazda)
  • W przypadku „nasłuchiwania” serwera zezwól na ponowne użycie adresu portu przy użyciu enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(lub SO_REUSEADDR), aby wiele serwerów mogło działać pod tym samym adresem IP
  • W przypadku „skanera” klienta należy włączyć rozgłaszanie w gnieździe UDP przy użyciu enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(lub SO_BROADCAST), w przeciwnym razie nie można wysłać na adres rozgłoszeniowy. Jest to tylko funkcja bezpieczeństwa , która utrudnia przypadkowe zalanie sieci.

Niestety nie jest to rozwiązanie „lekkie”; przykładowy projekt osiąga w sumie kilkaset LOC. Byłoby miło, gdyby zostały one spakowane do biblioteki narzędziowej dla ENet, ale zauważyłem, że w przypadku serwerów gier często chcesz wysłać więcej informacji specyficznych dla gry wraz z odpowiedzią serwera, aby były one przydatne, takie jak:

  • Rodzaj gry (np. „Kooperacja”, „deathmatch”)
  • „Mapa”, „poziom” lub „kampania”, na której działa serwer
  • Liczba graczy i maksymalna liczba graczy na serwerze
  • Wszelkie inne informacje związane z grą, które będą miały wpływ na decyzję klienta o połączeniu lub nie. Pomyśl o „przeglądarkach serwerów” w grach i rodzaju wyświetlanych informacji.
congusbongus
źródło
Właśnie o tym myślałem. Nadawanie jest właściwą drogą.
Lolums
3

Kiedy nie chcesz opuszczać biblioteki, możesz po prostu użyć brutalnej siły i spróbować połączyć się z każdym z możliwych adresów. Większość linii domowych to sieci klasy C (/ 24), w których pierwsze 24 bity adresu IP są takie same, a ostatnie 8 bitów różnią się. Masz więc tylko 255 możliwych adresów IP.

Nadal jednak transmisja UDP byłaby czystszą alternatywą. Wystarczy wysłać pakiet UDP na numer 255.255.255.255, a otrzymają go wszyscy klienci za tym samym routerem. Następnie mogą wysłać odpowiedź na źródłowy adres IP i źródłowy port pakietu, aby poinformować nadawcę, że są obecni.

Philipp
źródło
2
Proszę proszę proszę proszę proszę nie brute-force.
Trevor Powell
@TrevorPowell ... ponieważ ...?
Filip
2
Ponieważ to złe rozwiązanie. Nie będzie działać na uniwersytetach (które nie korzystają z sieci klasy c) ani w przedsiębiorstwach (które zwykle również nie korzystają z sieci klasy c), a personel IT w obu przypadkach będzie bardzo nie lubił obciążenia powodowanego przez każdego gracza Brute-Force próbuje wysyłać wiadomości na każdy adres IP w swojej sieci za każdym razem, gdy klikną przycisk „Odśwież”. To po prostu złe rozwiązanie problemu . To pytanie o lokalizację potencjalnych rówieśników bez serwera matematycznego jest dokładnie tym, do czego służy transmisja. Użyj transmisji. Jest lepszy pod każdym względem. :)
Trevor Powell,
1

Możesz rzucić okiem na DNS-SD / ZeroConf / Avahi / Bonjour / mDNS . Jest to rzecz, której Apple używa do udostępniania drukarek, folderów iTunes i tak dalej, ale została zaadaptowana gdzie indziej. Avahi jest wersją opensource używaną przez Linuksa (nie jestem pewien, czy to tylko Linux), nie jestem pewien, jak przenośna jest cała rzecz (chociaż istnieją implementacje dla większości platform).

Powiedziawszy to wszystko, prawdopodobnie łatwiej jest po prostu przeprowadzić transmisję UDP.

David C. Bishop
źródło