Справка по пробиванию отверстий UDP - PullRequest
4 голосов
/ 22 июля 2011

Я пытаюсь добавить сеть через Интернет в мою игру, используя Peer to Peer. Я уже реализовал версию только для локальной сети, которая использует одноранговые классы .NET для подключения в локальной сети.

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

Вот как я начал это реализовывать: Сервер - это HTTP-сервер, использующий очень простые PHP-скрипты для выполнения работы.

    • зарегистрировать имя на сервере, отправив частный IP-адрес и порт в виде переменной GET
    • когда сервер получает запрос на регистрацию, он сохраняет открытую конечную точку и частную конечную точку
    • запрос на подключение к другому клиенту.
    • сервер вернет частные и публичные конечные точки клиента
    • каждые две секунды, второй клиент будет регистрироваться на сервере, и если есть другой клиент, пытающийся подключиться к нему, он также получит свои конечные точки
    • оба клиента начинают спамить открытые конечные точки друг друга, пока не получат правильный ответ

Теперь у меня есть куча вопросов

  1. Может ли сервер быть HTTP-сервером?
  2. Когда я делаю запрос к HTTP-серверу, порт клиента меняется каждый раз, когда делается запрос. Всегда ли частная конечная точка сопоставляется с одной и той же общедоступной конечной точкой?
  3. Должен ли запрос к серверу иметь ту же конечную точку источника, что и UDP-сообщения клиенту?
  4. Есть ли способ подключиться к серверу HTTP в C #, используя указанную конечную точку источника?
  5. Есть ли проблемы с моей реализацией?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 22 июля 2011

Пробивание UDP - сложная тема, и было предпринято много попыток найти решение, которое работает. Проблема в том, что существует так много разных маршрутизаторов NAT, и не существует стандартного способа реализации NAT, поэтому все маршрутизаторы ведут себя немного по-разному.

Некоторые попытки были стандартизированы, например, STUN , ЛЕД . Они по-прежнему работают только в большинстве случаев, но не во всех, но они накапливают много знаний и решают многие проблемы - больше, чем ваша попытка когда-либо сможет, просто потому, что вы не можете протестировать свое решение с каждым маршрутизатором NAT под солнцем , Например, Skype потратил годы на совершенствование своего механизма обхода NAT.

Я рекомендую вам взглянуть на STUN или предпочтительно ICE . Попробуйте реализовать одну из них или поищите существующие реализации.

Другим вариантом может быть простое создание порта переадресации на маршрутизаторе, например используя UPnP или NAT-PMP .

Тем не менее, я не удивлюсь, если одноранговые классы .NET будут оснащены механизмом обхода NAT, но я не знаком с ними.

0 голосов
/ 30 апреля 2014

STUN - лучшее решение проблемы. это работает для большинства сценариев. Вот простой пример (C #), который дает вам тип NAT, локальный IP: порт и публичный IP: порт.

       try
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(new IPEndPoint(IPAddress.Any, 0));

            STUN_Result result = STUN_Client.Query("stunserver.org", 3478, socket);
            Console.WriteLine("Net Type : " + result.NetType.ToString());
            Console.WriteLine("Local IP : " + socket.LocalEndPoint.ToString());
            if (result.NetType != STUN_NetType.UdpBlocked)
            {
                Console.WriteLine("Public IP : " + result.PublicEndPoint.ToString());
            }
            else
            {
                Console.WriteLine("");
            }
        }
        catch (Exception x)
        {
            Console.WriteLine(x.StackTrace.ToString());
        }

Вы можете просто добавить несколько точек останова и проверить поведение кода.

также вы можете пройти через NAT, используя слова vs2010 (.net4.0 <). есть метод AllowNATTraversal (значение bool). установите значение true для NAT Traverse. Он использует адрес Ipv6 для подключения. Вы можете получить глобальный адрес Ipv6 с сервера «Teredo», написав несколько команд в командной строке. На самом деле IPV6 - это технология, которая используется, чтобы избежать этой проблемы. </p>

...