Рішення для виявлення легких однолітків локальної мережі?


9

Я створив бібліотеку для суто платформного програмування. Мої ігри, зроблені з ним, відмінно працюють в Android, ПК, Linux, Mac тощо.

Можливості роботи в мережі забезпечуються бібліотекою ENET, тому вся комунікація між моїми програмами не сумісна з TCP або UDP, а лише в користувацькому протоколі, навіть якщо це в залежності від UDP.

Я не думаю, що це можливо робити ENET, що я хочу, тому я прошу тут допомоги!

Скажімо, у мене однакова гра працює в телефоні Android, на моєму ноутбуці та на ПК. Всі вони знаходяться в одній мережі Wi-Fi, а отже, і в локальній мережі, будь то точка доступу Wifi (?) Чи побутовий маршрутизатор.

Мені потрібен кожен із цих 3 однолітків, щоб виявити інших двох в мережі. Це покликане лише знайти IP живих додатків у мережі LAN, щоб мати змогу розміщувати між собою багатокористувацькі ігри.

Я можу придумати лише один ефективний спосіб зробити це - трансляція UDP, очікування відповідей, але якщо це рішення, мені потрібно щось невелике, оскільки його єдина мета реалізації.

Іншим способом може бути спробувати підключитися до всіх IP-адрес у піддіапазоні локальної мережі, але я не думаю, що ОС буде зі мною на цьому: p


2
Я думаю, що декілька трансляцій UDP - це дорога, і я не розумію ваших заперечень проти цього, чи ENET не підтримує трансляцію?
Рой Т.

Точно так, це не так, він може транслювати лише вже відомих однолітків ..
Грімшо

stackoverflow.com/questions/683624/… Чи впливає це на відповідь?
Грімшо

Відповіді:


5

Як вже багато людей говорили, рішенням було б використання трансляції UDP , але тут є багато деталей щодо впровадження. Нещодавно я зіткнувся з тією ж проблемою, і після розробки рішення я створив допис у блозі та зразок проекту у вигляді сервера / клієнта LAN чату. Я підсумую їх тут, але ви повинні ознайомитися з ними для отримання більш детальної інформації та реального коду.

Ось як це працює на основі опису Лі Зальцмана, творця ENet:

  • Ваш ігровий сервер працює на одному сокеті як хост ENet
  • Сервер також прив'язується до відомого порту "прослуховування" як звичайний сокет UDP (тобто не хост ENet)
  • Клієнт відправляє широкомовне повідомлення UDP (тобто IP 255.255.255.255) на цей порт прослуховування і чекає відповідей
  • Усі сервери в локальній мережі отримають це "скануюче" повідомлення та відповідуть. В ідеалі ви можете відповісти через порт, на якому працює ігровий сервер (хост ENet); таким чином вам не потрібно, щоб ваш ігровий сервер працював на фіксованому порту)
  • Після того, як клієнт отримав кілька відповідей, він дізнається, які сервери є. Тоді ви можете вибрати одну з них, до якої потрібно підключитися, як звичайного однолітця ENet. На даний момент клієнт більше не потребує розетці "сканера" ​​UDP.

Хороша новина полягає в тому, що ENet надає функції обгортки для використання розеток , тому ви можете робити все в ENet. Погана новина полягає в тому, що обгортка надзвичайно тонка; вам потрібно знати про програмування сокетів , наприклад, що select()робить. Ось чому я закликаю вас поглянути на публікацію в блозі та зразок проекту, щоб ви могли скопіювати / вставити код і заощадити багато часу.

Ось деякі замітки та підводні камені, якщо ви вирішите зробити власну реалізацію:

  • Слухач / сканер повинен мати UDP, тому їх потрібно створити за допомогою enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(або SOCK_DGRAMдля звичайного програмування старого сокета)
  • Для "слухача" сервера дозвольте повторно використовувати адресу порту за допомогою enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(або SO_REUSEADDR), щоб кілька серверів могли працювати на одному IP
  • Для клієнтського "сканера" ​​ви повинні ввімкнути трансляцію в UDP-розетці за допомогою enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(або SO_BROADCAST), інакше ви не можете надсилати на адресу широкомовної програми. Це лише функція безпеки , що ускладнює випадкове затоплення мережі.

На жаль, це не зовсім "легке" рішення; зразковий проект працює на декілька сотень LOC загалом. Було б добре, якби це було упаковано у бібліотеку утиліт для ENet, але я виявив, що для ігрових серверів ви часто хочете надіслати ще якусь інформацію про ігри з відповіддю сервера, щоб зробити це корисним, наприклад:

  • Тип гри (наприклад, "кооператив", "смертний матч")
  • Сервер "карта", "рівень" або "кампанія" працює
  • Кількість гравців та максимум гравців для сервера
  • Будь-яка інша інформація, що стосується гри, яка впливатиме на рішення клієнта підключитися чи ні. Подумайте про "браузери серверів" в іграх та інформацію, яку вони показують.

Це саме те, що я думав. Мовлення - це шлях.
Лолум

3

Коли ви не хочете залишати свою бібліотеку, ви можете просто використовувати грубу силу та спробувати підключитися до кожної з можливих адрес. Більшість домашніх смуг - це мережі класу С (/ 24), де перший 24-бітовий IP-адресу однаковий, а останні 8-бітні відрізняються. Отже, у вас є лише 255 можливих IP-адрес.

Але все-таки здійснення трансляції UDP було б чистішою альтернативою. Просто надішліть пакет UDP на 255.255.255.255, і всі клієнти, що стоять за тим же маршрутизатором, отримають його. Потім вони можуть надіслати відповідь на вихідний IP та вихідний порт пакета, щоб повідомити відправника, що він присутній.


2
Будь ласка, будь ласка, будь ласка .
Тревор Пауелл

@TrevorPowell ... тому що ...?
Філіп

2
Тому що це неправильне рішення. Він не працюватиме в університетах (які не використовують мережі класу c) або на підприємствах (які також зазвичай не використовують мережі класу c), і ІТ-персонал або сильно не сподобається навантаженню, спричиненому тим, що кожен гравець робить грубі сили намагаються надсилати повідомлення на будь-яку IP-адресу своєї мережі щоразу, коли натискають кнопку "оновити". Це просто погане рішення проблеми . Це питання про пошук потенційних ровесників без математичного сервера - саме те, для чого призначено трансляцію. Використовуйте трансляцію. Краще всіляко. :)
Тревор Пауелл

1

Ви можете подивитися DNS-SD / ZeroConf / Avahi / Bonjour / mDNS . Це те, що Apple використовує для спільного використання принтерів, папок iTunes тощо, але це було прийнято в іншому місці. Avahi - це версія з відкритим кодом, яку використовує Linux (не впевнений, чи це лише Linux), не впевнений, наскільки це все переносно (хоча є реалізація для більшості платформ).

Сказавши все це, можливо, простіше просто зробити трансляцію UDP.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.