Решение для облегченного поиска одноранговых сетей?

9

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

Сетевые возможности обеспечиваются библиотекой ENET, поэтому вся связь между моими приложениями не совместима с TCP или UDP, а только в настраиваемом протоколе, даже в конечном счете основанном на UDP.

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

Допустим, у меня на Android-телефоне, ноутбуке и компьютере запущена одна и та же игра. Все они находятся в одной сети Wi-Fi и, следовательно, в локальной сети, будь то точка доступа Wi-Fi (?) Или домашний маршрутизатор.

Мне нужно, чтобы каждый из этих трех пиров обнаружил двух других в сети. Это предназначено только для того, чтобы найти IP живых приложений в сети LAN, чтобы иметь возможность размещать многопользовательские игры между ними.

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

Другим способом может быть попытка подключиться ко всем IP-адресам в поддиапазоне адресов LAN, но я не думаю, что ОС будет со мной на этом: p

Гримшоу
источник
2
Я думаю, что стоит использовать несколько UDP-трансляций, и я не понимаю ваших возражений против этого, или ENET не поддерживает трансляции?
Рой Т.
Точно, это не так, он может вещать только для уже известных пэров ..
Grimshaw
stackoverflow.com/questions/683624/… Это влияет на ответ?
Гримшоу

Ответы:

5

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

Вот как это работает, основываясь на описании Ли Зальцмана, создателя 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, но я обнаружил, что для игровых серверов вы часто хотите отправить дополнительную информацию, специфичную для игры, с ответом сервера, чтобы сделать это полезным, например:

  • Тип игры (например, «кооператив», «Deathmatch»)
  • «Карта», «уровень» или «кампания», на которой работает сервер
  • Количество игроков и максимальное количество игроков на сервере
  • Любая другая информация, относящаяся к игре, которая повлияет на решение клиента подключиться или нет. Подумайте о «браузерах серверов» в играх и о том, какую информацию они показывают.
congusbongus
источник
Это именно то, о чем я думал. Вещание - это путь.
Lolums
3

Если вы не хотите покидать свою библиотеку, вы можете просто использовать грубую силу и попытаться подключиться к каждому из возможных адресов. Большинство домашних сетей представляют собой сети класса C (/ 24), в которых первые 24 бита IP-адреса совпадают, а последние 8 бит отличаются. Таким образом, у вас есть только 255 возможных IP-адресов.

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

Philipp
источник
2
Пожалуйста , пожалуйста , пожалуйста , пожалуйста , пожалуйста , не грубой силы.
Тревор Пауэлл
@TrevorPowell ... потому что ...?
Филипп
2
Потому что это неправильное решение. Он не будет работать в университетах (которые не используют сети класса c) или на предприятиях (которые также обычно не используют сети класса c), и ИТ-персоналу либо сильно не понравится нагрузка, вызванная тем, что каждый игрок делает brute-force пытается отправлять сообщения на каждый IP-адрес в своей сети каждый раз, когда нажимает кнопку «обновить». Это просто плохое решение проблемы . Этот вопрос поиска потенциальных пиров без математического сервера - именно то, для чего нужна трансляция. Используйте трансляцию. Это лучше во всех отношениях. :)
Тревор Пауэлл
1

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

Сказав все это, вероятно, проще сделать UDP-трансляцию.

Дэвид С. Бишоп
источник